tests/test.sh exit code (0 → resolved); the classification below is post-hoc and cannot change it.// UART-style byte receiver.
//
// Line idles high. A byte is one low start bit, eight data bits LSB first,
// then one high stop bit, each BITLEN clock cycles.
//
// - rx_i is synchronized through two flops; the synchronized line drives
// all decisions.
// - A start is accepted the exact cycle a fresh low (from the high-to-low
// edge) reaches floor(BITLEN/2) low cycles; a shorter low starts nothing.
// - Data bits and the stop bit are sampled at bit-period centers. Sampling
// the stop bit pulses valid_o for one cycle, with the byte on data_o and
// frame_err_o high if the stop bit was low.
// - break_o is a level: high once the synchronized line has been low for six
// continuous bit periods, staying high until the line is high again. A
// break preempts any in-progress frame (that byte is dropped). After
// break_o falls the line must hold high six bit periods before a start is
// accepted again (any low restarts that wait).
// - When a break interrupts a byte, d = number of data bits it had sampled
// (0 if none). The next d delivered bytes force frame_err_o high; a further
// break replaces any pending count with its own d.
//
// All outputs are registered; rst is synchronous, active-high, clearing every
// output to 0.
module TopModule #(
parameter BITLEN = 16
) (
input wire clk,
input wire rst,
input wire rx_i,
output reg [7:0] data_o,
output reg valid_o,
output reg frame_err_o,
output reg break_o
);
localparam integer HALF = BITLEN/2; // floored half bit period
localparam integer LOWMAX = 6*BITLEN; // six bit periods, in cycles
localparam integer CW = $clog2(6*BITLEN + 2);
localparam integer SW = (BITLEN <= 1) ? 1 : $clog2(BITLEN);
// Two-flop synchronizer for rx_i (idles high).
reg rx_meta, rx_sync;
// Continuous low / high run lengths of the synchronized line, in cycles.
reg [CW-1:0] low_cnt, high_cnt;
reg recovering; // waiting for six high bit periods after a break
// Frame receiver.
localparam [1:0] FS_IDLE = 2'd0,
FS_DATA = 2'd1,
FS_STOP = 2'd2;
reg [1:0] state;
reg [SW-1:0] samp_cnt; // cycles since last sample
reg [3:0] bit_idx; // data bits sampled so far (0..8)
reg [7:0] shifter; // assembled byte
// Number of upcoming delivered bytes whose frame_err_o is forced high.
reg [3:0] force_cnt;
reg break_rise; // combinational temp
always @(posedge clk) begin
if (rst) begin
rx_meta <= 1'b1;
rx_sync <= 1'b1;
low_cnt <= '0;
high_cnt <= '0;
recovering <= 1'b0;
state <= FS_IDLE;
samp_cnt <= '0;
bit_idx <= 4'd0;
shifter <= 8'd0;
force_cnt <= 4'd0;
data_o <= 8'd0;
valid_o <= 1'b0;
frame_err_o <= 1'b0;
break_o <= 1'b0;
end else begin
// Synchronizer (uses the current rx_sync for this cycle's logic).
rx_meta <= rx_i;
rx_sync <= rx_meta;
// One-cycle strobes default low.
valid_o <= 1'b0;
frame_err_o <= 1'b0;
// ---- Break detection over the synchronized line ----
break_rise = (rx_sync == 1'b0) && (!break_o) &&
((low_cnt + 1) >= LOWMAX);
if (rx_sync == 1'b0) begin
if (low_cnt < LOWMAX)
low_cnt <= low_cnt + 1'b1;
high_cnt <= '0;
if (break_rise)
break_o <= 1'b1;
end else begin
low_cnt <= '0;
if (high_cnt < LOWMAX)
high_cnt <= high_cnt + 1'b1;
if (break_o) begin
// Break just ended: begin the post-break high recovery.
break_o <= 1'b0;
recovering <= 1'b1;
end else if (recovering && ((high_cnt + 1) >= LOWMAX)) begin
recovering <= 1'b0;
end
end
// ---- Frame receiver ----
case (state)
FS_IDLE: begin
// Accept a fresh low that has reached the half bit period,
// unless still recovering from a break.
if (!recovering && (rx_sync == 1'b0) &&
((low_cnt + 1) == HALF)) begin
state <= FS_DATA;
samp_cnt <= '0;
bit_idx <= 4'd0;
end
end
FS_DATA: begin
if (samp_cnt == (BITLEN-1)) begin
shifter[bit_idx[2:0]] <= rx_sync; // LSB first
samp_cnt <= '0;
bit_idx <= bit_idx + 4'd1;
if (bit_idx == 4'd7)
state <= FS_STOP;
end else begin
samp_cnt <= samp_cnt + 1'b1;
end
end
FS_STOP: begin
if (samp_cnt == (BITLEN-1)) begin
data_o <= shifter;
valid_o <= 1'b1;
frame_err_o <= (rx_sync == 1'b0) || (force_cnt != 4'd0);
if (force_cnt != 4'd0)
force_cnt <= force_cnt - 4'd1;
state <= FS_IDLE;
samp_cnt <= '0;
bit_idx <= 4'd0;
end else begin
samp_cnt <= samp_cnt + 1'b1;
end
end
default: state <= FS_IDLE;
endcase
// ---- A break preempts any in-progress frame ----
if (break_rise) begin
if (state != FS_IDLE) begin
// Drop the byte; record how many data bits it sampled.
force_cnt <= (state == FS_STOP) ? 4'd8 : bit_idx;
valid_o <= 1'b0;
end else begin
// No byte interrupted: d = 0 replaces any pending count.
force_cnt <= 4'd0;
end
state <= FS_IDLE;
samp_cnt <= '0;
bit_idx <= 4'd0;
end
end
end
endmodule
Lint/compile check the module
(command -v verilator && verilator --lint-only -Wall --top-module TopModule dut.sv 2>&1 | head -40) || (command -v iverilog && iverilog -g2012 -o /tmp/dut.out dut.sv 2>&1 | head -40) || echo "no simulator found"
/usr/bin/iverilog [stdout] /usr/bin/iverilog
Run smoke test
cat > /tmp/tb.sv <<'EOF'
module tb;
localparam BITLEN=8;
reg clk=0, rst=1, rx=1;
wire [7:0] data; wire valid, ferr, brk;
TopModule #(.BITLEN(BITLEN)) dut(.clk(clk),.rst(rst),.rx_i(rx),
.data_o(data),.valid_o(valid),.frame_err_o(ferr),.break_o(brk));
always #5 clk=~clk;
task send_byte(input [7:0] b, input stopbit);
integer i;
begin
rx=0; repeat(BITLEN) @(posedge clk); // start
for(i=0;i<8;i=i+1) begin rx=b[i]; repeat(BITLEN) @(posedge clk); end
rx=stopbit; repeat(BITLEN) @(posedge clk); // stop
rx=1;
end
endtask
always @(posedge clk) if(valid) $display(" VALID data=%02x ferr=%b brk=%b @%0t",data,ferr,brk,$time);
always @(posedge clk) if(brk) $display(" BREAK high @%0t",$time);
initial begin
repeat(3) @(posedge clk); rst=0; @(posedge clk);
$display("send 0xA5 good stop");
send_byte(8'hA5,1); repeat(2)@(posedge clk);
$display("send 0x3C bad stop (framing err)");
send_byte(8'h3C,0); repeat(2)@(posedge clk); rx=1; repeat(BITLEN*8)@(posedge clk);
$display("send all-low byte (self break)");
send_byte(8'h00,0); repeat(2)@(posedge clk); rx=1;
repeat(BITLEN*8)@(posedge clk);
$display("after recovery send 0x55 -> should be forced framing err for d bytes");
send_byte(8'h55,1); repeat(2)@(posedge clk);
send_byte(8'hFF,1); repeat(2)@(posedge clk);
repeat(4)@(posedge clk);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/dut.out /tmp/tb.sv /app/dut.sv && vvp /tmp/dut.outsend 0xA5 good stop VALID data=a5 ferr=0 brk=0 @825 send 0x3C bad stop (framing err) VALID data=3c ferr=1 brk=0 @1645 send all-low byte (self break) BREAK high @2825 BREAK high @2835 BREAK high @2845 BREAK high @2855 BREAK high @2865 BREAK high @2875 BREAK high @2885 BREAK high @2895 BREAK high @2905 BREAK high @2915 BREAK high @2925 BREAK high @2935 BREAK high @2945 BREAK high @2955 BREAK high @2965 BREAK high @2975 BREAK high @2985 BREAK high @2995 BREAK high @3005 BREAK high @3015 BREAK high @3025 BREAK high @3035 BREAK high @3045 BREAK high @3055 BREAK high @3065 BREAK high @3075 BREAK high @3085 BREAK high @3095 BREAK high @3105 BREAK high @3115 BREAK high @3125 BREAK high @3135 BREAK high @3145 after recovery send 0x55 -> should be forced framing err for d bytes VALID data=55 ferr=1 brk=0 @4565 VALID data=ff ferr=1 brk=0 @5385 /tmp/tb.sv:35: $finish called at 5455 (1s) [stdout] send 0xA5 good stop VALID data=a5 ferr=0 brk=0 @825 send 0x3C bad stop (framing err) VALID data=3c ferr=1 brk=0 @1645 send all-low byte (self break) BREAK high @2825 BREAK high @2835 BREAK high @2845 BREAK high @2855 BREAK high @2865 BREAK high @2875 BREAK high @2885 BREAK high @2895 BREAK high @2905 BREAK high @2915 BREAK high @2925 BREAK high @2935 BREAK high @2945 BREAK high @2955 BREAK high @2965 BREAK high @2975 BREAK high @2985 BREAK high @2995 BREAK high @3005 BREAK high @3015 BREAK high @3025 BREAK high @3035 BREAK high @3045 BREAK high @3055 BREAK high @3065 BREAK high @3075 BREAK high @3085 BREAK high @3095 BREAK high @3105 BREAK high @3115 BREAK high @3125 BREAK high @3135 BREAK high @3145 after recovery send 0x55 -> should be forced framing err for d bytes VALID data=55 ferr=1 brk=0 @4565 VALID data=ff ferr=1 brk=0 @5385 /tmp/tb.sv:35: $finish called at 5455 (1s)
No file changes, the agent left the workspace untouched.
TEST dut_present: PASS (/app/dut.sv exists)
TEST dut_forbidden: PASS (no forbidden constructs)
TEST dut_compiles: PASS (compiled with held-back reference/testbench)
TEST simulation_completed: PASS (Mismatches: 292 in 8633 samples)
TEST reference_equivalence: FAIL (292 mismatches in 8633 samples)
{"score": 0.000000, "results_file": "/tmp/h2t-grader-home.7jbvG1/runtime/cb_verifier_314-1077-13656-15670_314/results.jsonl"}Reproduce this trial: git checkout 2f94510 && PYTHONPATH=src python3 scripts/build_site.py , then open trial/trial_3931160f210f4f28. Re-running the agent live requires EVAL_PLATFORM_ENABLE_OAUTH_SMOKE=1 and is non-deterministic.
Trial trial_3931160f210f4f28 · verifier authoritative; classifier explanatory.