tests/test.sh exit code (0 → resolved); the classification below is post-hoc and cannot change it.module TopModule #(
parameter int BITLEN = 16
) (
input logic clk,
input logic rst,
input logic rx_i,
output logic [7:0] data_o,
output logic valid_o,
output logic frame_err_o,
output logic break_o
);
// Half a bit period (floored), a full break span (six bit periods),
// and a counter width big enough to reach it.
localparam int HALF = BITLEN/2;
localparam int BRK = 6*BITLEN;
localparam int CW = $clog2(6*BITLEN+1);
// ---- two-flop synchronizer (the line idles high) --------------------
logic rx_meta, rx_sync;
always_ff @(posedge clk) begin
if (rst) begin
rx_meta <= 1'b1;
rx_sync <= 1'b1;
end else begin
rx_meta <= rx_i;
rx_sync <= rx_meta;
end
end
// ---- continuous low / high run counters -----------------------------
logic [CW-1:0] low_cnt, high_cnt;
// ---- combinational break / recovery events --------------------------
logic set_break, brk_rise, high_reached;
assign set_break = (~rx_sync) & (low_cnt >= CW'(BRK-1));
assign brk_rise = set_break & ~break_o; // rising edge of break
assign high_reached = ( rx_sync) & (high_cnt >= CW'(BRK-1));
// ---- frame reception FSM --------------------------------------------
typedef enum logic [1:0] {IDLE, DATA, STOP} state_t;
state_t state;
logic [CW-1:0] timer; // cycles until next bit-center sample
logic [3:0] bit_idx; // data bits sampled so far (0..8)
logic [7:0] data_sh; // shift register (LSB first)
logic locked; // post-break: block starts until 6-bit high
logic [3:0] ferr_pending; // remaining bytes to force frame_err (= d)
always_ff @(posedge clk) begin
if (rst) begin
low_cnt <= '0;
high_cnt <= '0;
state <= IDLE;
timer <= '0;
bit_idx <= '0;
data_sh <= '0;
locked <= 1'b0;
ferr_pending <= '0;
data_o <= '0;
valid_o <= 1'b0;
frame_err_o <= 1'b0;
break_o <= 1'b0;
end else begin
// registered pulse outputs default low
valid_o <= 1'b0;
frame_err_o <= 1'b0;
// continuous-run counters (saturate at BRK)
if (rx_sync) begin
high_cnt <= (high_cnt == CW'(BRK)) ? CW'(BRK) : high_cnt + 1'b1;
low_cnt <= '0;
end else begin
low_cnt <= (low_cnt == CW'(BRK)) ? CW'(BRK) : low_cnt + 1'b1;
high_cnt <= '0;
end
// break is a registered level: high while six low periods have elapsed
break_o <= set_break;
// lock after a break; release once the line holds high six bit periods
if (brk_rise) locked <= 1'b1;
else if (high_reached) locked <= 1'b0;
// A break preempts any frame in progress.
if (brk_rise) begin
// d = data bits the interrupted byte sampled (0 if none / no frame);
// a further break replaces any pending count with its own d.
ferr_pending <= (state == DATA || state == STOP) ? bit_idx : 4'd0;
state <= IDLE;
bit_idx <= '0;
timer <= '0;
end else begin
case (state)
IDLE: begin
// Accept a start the cycle a fresh low reaches half a bit period.
if (!locked && !rx_sync && (low_cnt == CW'(HALF))) begin
state <= DATA;
timer <= CW'(BITLEN-1);
bit_idx <= '0;
data_sh <= '0;
end
end
DATA: begin
if (timer == '0) begin
data_sh <= {rx_sync, data_sh[7:1]}; // LSB first
timer <= CW'(BITLEN-1);
bit_idx <= bit_idx + 1'b1;
if (bit_idx == 4'd7)
state <= STOP;
end else begin
timer <= timer - 1'b1;
end
end
STOP: begin
if (timer == '0) begin
valid_o <= 1'b1;
data_o <= data_sh;
// frame error if stop bit low, or forced for the next d bytes
frame_err_o <= (~rx_sync) | (ferr_pending != 0);
if (ferr_pending != 0)
ferr_pending <= ferr_pending - 1'b1;
state <= IDLE;
bit_idx <= '0;
end else begin
timer <= timer - 1'b1;
end
end
default: state <= IDLE;
endcase
end
end
end
endmodule
Check for available Verilog tools
which verilator iverilog 2>/dev/null; echo "---"
/usr/bin/iverilog --- [stdout] /usr/bin/iverilog ---
Compile with iverilog SystemVerilog
iverilog -g2012 -o /tmp/dut.out dut.sv 2>&1 && echo "COMPILE OK"
COMPILE OK [stdout] COMPILE OK
Run basic reception testbench
cat > /tmp/tb.sv <<'EOF'
module tb;
localparam BITLEN=8;
logic clk=0, rst=1, rx=1;
logic [7:0] data; logic valid, ferr, brk;
TopModule #(.BITLEN(BITLEN)) dut(.clk,.rst,.rx_i(rx),.data_o(data),.valid_o(valid),.frame_err_o(ferr),.break_o(brk));
always #5 clk=~clk;
task drivebit(input logic b); repeat(BITLEN) @(posedge clk) rx<=b; endtask
int caught=0;
always @(posedge clk) if(valid) begin
$display("VALID data=%02x ferr=%b brk=%b @%0t",data,ferr,brk,$time); caught++;
end
initial begin
@(posedge clk) rst<=1; @(posedge clk) rst<=0; rx<=1;
repeat(3) @(posedge clk);
// send byte 0xA5 = 1010_0101, LSB first
drivebit(0); // start
for(int i=0;i<8;i++) drivebit((8'hA5>>i)&1);
drivebit(1); // stop
repeat(5) @(posedge clk);
// send byte 0x3C with bad (low) stop -> frame_err
drivebit(0);
for(int i=0;i<8;i++) drivebit((8'h3C>>i)&1);
drivebit(0); // bad stop
repeat(8) @(posedge clk);
if(caught!=2) $display("FAIL count=%0d",caught); else $display("BASIC OK");
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t.out /tmp/dut_and_tb.sv 2>/dev/null; iverilog -g2012 -s tb -o /tmp/t.out dut.sv /tmp/tb.sv 2>&1 && vvp /tmp/t.outVALID data=a5 ferr=0 brk=0 @855 VALID data=3c ferr=1 brk=0 @1705 BASIC OK /tmp/tb.sv:29: $finish called at 1775 (1s) [stdout] VALID data=a5 ferr=0 brk=0 @855 VALID data=3c ferr=1 brk=0 @1705 BASIC OK /tmp/tb.sv:29: $finish called at 1775 (1s)
Run break and recovery testbench
cat > /tmp/tb2.sv <<'EOF'
module tb;
localparam BITLEN=8;
logic clk=0, rst=1, rx=1;
logic [7:0] data; logic valid, ferr, brk;
TopModule #(.BITLEN(BITLEN)) dut(.clk,.rst,.rx_i(rx),.data_o(data),.valid_o(valid),.frame_err_o(ferr),.break_o(brk));
always #5 clk=~clk;
task drivebit(input logic b); repeat(BITLEN) @(posedge clk) rx<=b; endtask
task sendbyte(input logic[7:0] v, input logic stop);
drivebit(0); for(int i=0;i<8;i++) drivebit((v>>i)&1); drivebit(stop);
endtask
logic brk_seen=0;
always @(posedge clk) begin
if(brk & ~brk_seen) begin $display("BREAK rise @%0t",$time); brk_seen<=1; end
if(~brk & brk_seen) begin $display("BREAK fall @%0t",$time); brk_seen<=0; end
if(valid) $display("VALID data=%02x ferr=%b @%0t",data,ferr,$time);
end
initial begin
@(posedge clk) rst<=1; @(posedge clk) rst<=0; rx<=1;
repeat(4) @(posedge clk);
// hold line low long enough to trigger break (>=6 bit periods)
repeat(7*BITLEN) @(posedge clk) rx<=0;
// recovery: hold high 6 bit periods
repeat(7*BITLEN) @(posedge clk) rx<=1;
// now send several good bytes; first d should be forced frame_err
sendbyte(8'h11,1);
sendbyte(8'h22,1);
sendbyte(8'h33,1);
sendbyte(8'h44,1);
sendbyte(8'h55,1);
sendbyte(8'h66,1);
sendbyte(8'h77,1);
repeat(8) @(posedge clk);
$finish;
end
endmodule
EOF
iverilog -g2012 -s tb -o /tmp/t2.out dut.sv /tmp/tb2.sv 2>&1 && vvp /tmp/t2.outBREAK rise @575 BREAK fall @665 VALID data=11 ferr=1 @1985 VALID data=22 ferr=1 @2785 VALID data=33 ferr=1 @3585 VALID data=44 ferr=1 @4385 VALID data=55 ferr=1 @5185 VALID data=66 ferr=0 @5985 VALID data=77 ferr=0 @6785 /tmp/tb2.sv:35: $finish called at 6855 (1s) [stdout] BREAK rise @575 BREAK fall @665 VALID data=11 ferr=1 @1985 VALID data=22 ferr=1 @2785 VALID data=33 ferr=1 @3585 VALID data=44 ferr=1 @4385 VALID data=55 ferr=1 @5185 VALID data=66 ferr=0 @5985 VALID data=77 ferr=0 @6785 /tmp/tb2.sv:35: $finish called at 6855 (1s)
Test sub-half no-start and recovery restart
cat > /tmp/tb3.sv <<'EOF'
module tb;
localparam BITLEN=8;
logic clk=0, rst=1, rx=1;
logic [7:0] data; logic valid, ferr, brk;
TopModule #(.BITLEN(BITLEN)) dut(.clk,.rst,.rx_i(rx),.data_o(data),.valid_o(valid),.frame_err_o(ferr),.break_o(brk));
always #5 clk=~clk;
task drivebit(input logic b); repeat(BITLEN) @(posedge clk) rx<=b; endtask
int nv=0;
always @(posedge clk) if(valid) begin nv++; $display("VALID data=%02x ferr=%b @%0t",data,ferr,$time); end
initial begin
@(posedge clk) rst<=1; @(posedge clk) rst<=0; rx<=1;
repeat(4) @(posedge clk);
// sub-half low (3 cycles < HALF=4) then high -> no frame
repeat(3) @(posedge clk) rx<=0;
repeat(2*BITLEN) @(posedge clk) rx<=1;
if(nv==0) $display("SUBHALF-NOSTART OK"); else $display("FAIL: spurious frame");
// trigger break
repeat(7*BITLEN) @(posedge clk) rx<=0;
// recovery attempt but interrupted by a low before 6 high periods
repeat(3*BITLEN) @(posedge clk) rx<=1;
repeat(2) @(posedge clk) rx<=0; // brief low restarts high count
repeat(3*BITLEN) @(posedge clk) rx<=1; // not yet 6 continuous -> still locked
// try a start here: should be dropped because 6 high not yet held after restart
drivebit(0); for(int i=0;i<8;i++) drivebit(1); drivebit(1);
repeat(8) @(posedge clk);
$display("frames after interrupted recovery = %0d (expect 0 dropped-start note)",nv);
$finish;
end
endmodule
EOF
iverilog -g2012 -s tb -o /tmp/t3.out dut.sv /tmp/tb3.sv 2>&1 && vvp /tmp/t3.outSUBHALF-NOSTART OK frames after interrupted recovery = 0 (expect 0 dropped-start note) /tmp/tb3.sv:27: $finish called at 2185 (1s) [stdout] SUBHALF-NOSTART OK frames after interrupted recovery = 0 (expect 0 dropped-start note) /tmp/tb3.sv:27: $finish called at 2185 (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: 20 in 8633 samples)
TEST reference_equivalence: FAIL (20 mismatches in 8633 samples)
{"score": 0.000000, "results_file": "/tmp/h2t-grader-home.i8ndtE/runtime/cb_verifier_334-25421-14043-25804_334/results.jsonl"}Reproduce this trial: git checkout 2f94510 && PYTHONPATH=src python3 scripts/build_site.py , then open trial/trial_4cea056529704d43. Re-running the agent live requires EVAL_PLATFORM_ENABLE_OAUTH_SMOKE=1 and is non-deterministic.
Trial trial_4cea056529704d43 · verifier authoritative; classifier explanatory.