tests/test.sh exit code (0 → resolved); the classification below is post-hoc and cannot change it.// UART receiver with configurable baud/format, error flags, overflow and break detection.
module TopModule(
input clk,
input reset,
input in,
input [15:0] baud_div_i,
input [2:0] frame_fmt_i,
input clear_err_i,
input data_ack_i,
output reg [7:0] out_byte,
output reg done,
output reg parity_err_o,
output reg frame_err_o,
output reg break_o,
output reg ovf_o,
output reg [7:0] byte_count_o
);
localparam [2:0] S_IDLE = 3'd0,
S_START = 3'd1,
S_DATA = 3'd2,
S_PARITY = 3'd3,
S_STOP = 3'd4;
reg [2:0] state;
reg [20:0] clk_cnt; // clock index within current bit
reg [3:0] bit_idx; // data-bit / stop-bit index
reg [15:0] baud_lat; // latched baud (never zero)
reg [2:0] fmt_lat; // latched format
reg [7:0] data_reg; // received data (LSB first)
reg frame_bad; // this frame had a parity or frame error
reg in_prev; // previous serial sample (edge detect)
reg [24:0] low_cnt; // consecutive-low counter for break detect
// ------- format decode (from latched format) -------
reg [3:0] ndata;
reg par_en;
reg par_odd;
reg [1:0] nstop;
always @* begin
case (fmt_lat)
3'b001: begin ndata = 4'd7; par_en = 1'b0; par_odd = 1'b0; nstop = 2'd1; end // 7N1
3'b010: begin ndata = 4'd8; par_en = 1'b1; par_odd = 1'b0; nstop = 2'd1; end // 8E1
3'b011: begin ndata = 4'd8; par_en = 1'b1; par_odd = 1'b1; nstop = 2'd1; end // 8O1
3'b100: begin ndata = 4'd8; par_en = 1'b0; par_odd = 1'b0; nstop = 2'd2; end // 8N2
default:begin ndata = 4'd8; par_en = 1'b0; par_odd = 1'b0; nstop = 2'd1; end // 8N1
endcase
end
// ------- bit timing -------
wire [20:0] full = baud_lat * 21'd16; // clocks per bit
wire [20:0] half = baud_lat * 21'd8; // midpoint offset
wire at_mid = (clk_cnt == half - 21'd1);
wire at_end = (clk_cnt == full - 21'd1);
// ------- sample events -------
wire dp = (^data_reg) ^ in; // running parity incl. parity bit
wire parity_fail = (state == S_PARITY) && at_mid && (dp != par_odd);
wire frame_fail = (state == S_STOP) && at_mid && (in == 1'b0);
wire last_stop_end = (state == S_STOP) && at_end &&
(bit_idx == {2'b00, (nstop - 2'd1)});
wire commit = last_stop_end && !frame_bad;
wire new_parity_err = parity_fail;
wire new_frame_err = frame_fail;
wire new_ovf = commit && done && !data_ack_i;
// ------- break detection (live baud) -------
wire in_low = (in == 1'b0);
wire [24:0] brk_thresh = baud_div_i * 25'd176; // 11 * 16 * baud
wire [24:0] nlow = in_low ? ((low_cnt >= brk_thresh) ? low_cnt
: low_cnt + 25'd1)
: 25'd0;
wire brk_hit = (baud_div_i != 16'd0) && in_low && (nlow >= brk_thresh);
always @(posedge clk) begin
if (reset) begin
state <= S_IDLE;
clk_cnt <= 21'd0;
bit_idx <= 4'd0;
baud_lat <= 16'd0;
fmt_lat <= 3'd0;
data_reg <= 8'd0;
frame_bad <= 1'b0;
in_prev <= 1'b1;
out_byte <= 8'd0;
done <= 1'b0;
byte_count_o <= 8'd0;
parity_err_o <= 1'b0;
frame_err_o <= 1'b0;
ovf_o <= 1'b0;
break_o <= 1'b0;
low_cnt <= 25'd0;
end else begin
in_prev <= in;
// sticky error flags: clear on clear_err_i, but a same-cycle event wins
parity_err_o <= (parity_err_o && !clear_err_i) || new_parity_err;
frame_err_o <= (frame_err_o && !clear_err_i) || new_frame_err;
ovf_o <= (ovf_o && !clear_err_i) || new_ovf;
// done: commit sets it (overrides a same-cycle ack); ack otherwise clears it
if (commit) done <= 1'b1;
else if (data_ack_i) done <= 1'b0;
// good-frame commit updates byte and saturating count
if (commit) out_byte <= data_reg;
if (commit && (byte_count_o != 8'hFF)) byte_count_o <= byte_count_o + 8'd1;
// capture data bit at its midpoint (LSB first)
if (state == S_DATA && at_mid) data_reg[bit_idx[2:0]] <= in;
// accumulate frame error status (reset at frame start below)
if (state != S_IDLE)
frame_bad <= frame_bad || parity_fail || frame_fail;
// ------- frame FSM -------
case (state)
S_IDLE: begin
if (in_prev == 1'b1 && in == 1'b0) begin // idle high->low: start frame
baud_lat <= (baud_div_i == 16'd0) ? 16'd1 : baud_div_i;
fmt_lat <= frame_fmt_i;
state <= S_START;
clk_cnt <= 21'd1; // detect cycle counts as index 0
bit_idx <= 4'd0;
data_reg <= 8'd0;
frame_bad <= 1'b0;
end else begin
clk_cnt <= 21'd0;
end
end
S_START: begin
if (at_mid && in == 1'b1) begin // high start midpoint: abort, no flags
state <= S_IDLE; clk_cnt <= 21'd0;
end else if (at_end) begin
state <= S_DATA; clk_cnt <= 21'd0; bit_idx <= 4'd0;
end else begin
clk_cnt <= clk_cnt + 21'd1;
end
end
S_DATA: begin
if (at_end) begin
clk_cnt <= 21'd0;
if (bit_idx == ndata - 4'd1) begin
if (par_en) state <= S_PARITY;
else begin state <= S_STOP; bit_idx <= 4'd0; end
end else begin
bit_idx <= bit_idx + 4'd1;
end
end else begin
clk_cnt <= clk_cnt + 21'd1;
end
end
S_PARITY: begin
if (at_end) begin
state <= S_STOP; clk_cnt <= 21'd0; bit_idx <= 4'd0;
end else begin
clk_cnt <= clk_cnt + 21'd1;
end
end
S_STOP: begin
if (at_end) begin
if (bit_idx == {2'b00, (nstop - 2'd1)}) begin
state <= S_IDLE; clk_cnt <= 21'd0; // final stop slot done
end else begin
bit_idx <= bit_idx + 4'd1; clk_cnt <= 21'd0;
end
end else begin
clk_cnt <= clk_cnt + 21'd1;
end
end
default: state <= S_IDLE;
endcase
// ------- break detection -------
low_cnt <= nlow;
if (!in_low) break_o <= 1'b0; // deassert one clock after high
else break_o <= break_o || brk_hit;
end
end
endmodule
Compile/lint the SystemVerilog module
(iverilog -g2012 -o /tmp/dut_test dut.sv 2>&1 && echo "IVERILOG_OK") || (verilator --lint-only -Wno-lint dut.sv 2>&1 && echo "VERILATOR_OK") || echo "no simulator found"
IVERILOG_OK [stdout] IVERILOG_OK
Simulate a good 8N1 frame
cat > /tmp/tb.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1;
reg [2:0] frame_fmt_i=3'b000;
wire [7:0] out_byte; wire done, parity_err_o, frame_err_o, break_o, ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i;
// send one bit = 16 clocks
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
reg [7:0] data = 8'hA5; // 10100101
initial begin
@(posedge clk); reset=0; @(posedge clk);
// idle
in=1; repeat(4) @(posedge clk);
// start bit
sendbit(1'b0);
// 8 data bits LSB first
for(i=0;i<8;i=i+1) sendbit(data[i]);
// stop bit
sendbit(1'b1);
repeat(4) @(posedge clk);
$display("out_byte=%02x done=%b count=%0d perr=%b ferr=%b ovf=%b",
out_byte, done, byte_count_o, parity_err_o, frame_err_o, ovf_o);
if (out_byte==8'hA5 && done==1 && byte_count_o==1) $display("PASS good frame");
else $display("FAIL good frame");
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t /app/dut.sv /tmp/tb.sv && vvp /tmp/tout_byte=a5 done=1 count=x perr=x ferr=x ovf=x FAIL good frame /tmp/tb.sv:31: $finish called at 1695 (1s) [stdout] out_byte=a5 done=1 count=x perr=x ferr=x ovf=x FAIL good frame /tmp/tb.sv:31: $finish called at 1695 (1s)
Simulate good/error/overflow scenarios
cat > /tmp/tb.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1;
reg [2:0] frame_fmt_i=3'b000;
wire [7:0] out_byte; wire done, parity_err_o, frame_err_o, break_o, ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
task frame8N1(input [7:0] data, input stopbit);
begin sendbit(1'b0); for(i=0;i<8;i=i+1) sendbit(data[i]); sendbit(stopbit); end
endtask
initial begin
repeat(3) @(posedge clk); reset=0; in=1; repeat(4) @(posedge clk);
// ---- good frame ----
frame8N1(8'hA5, 1'b1); repeat(3) @(posedge clk);
$display("[good] out=%02x done=%b count=%0d ferr=%b perr=%b ovf=%b",
out_byte,done,byte_count_o,frame_err_o,parity_err_o,ovf_o);
// ack
data_ack_i=1; @(posedge clk); data_ack_i=0; @(posedge clk);
$display("[ack] done=%b", done);
// ---- framing error: stop bit low ----
repeat(4) @(posedge clk); frame8N1(8'h3C, 1'b0); repeat(3) @(posedge clk);
$display("[ferr] count=%0d ferr=%b done=%b", byte_count_o, frame_err_o, done);
// clear
clear_err_i=1; @(posedge clk); clear_err_i=0; @(posedge clk);
$display("[clr] ferr=%b", frame_err_o);
// ---- overflow: two good frames without ack ----
repeat(4) @(posedge clk); frame8N1(8'h11,1'b1); repeat(3) @(posedge clk);
frame8N1(8'h22,1'b1); repeat(3) @(posedge clk);
$display("[ovf] out=%02x count=%0d ovf=%b done=%b", out_byte,byte_count_o,ovf_o,done);
data_ack_i=1; @(posedge clk); data_ack_i=0;
// ---- even parity good (8E1) ----
reset=1; repeat(2) @(posedge clk); reset=0; frame_fmt_i=3'b010; in=1; repeat(4) @(posedge clk);
// data 8'h07 (three 1s) -> even parity bit = 1
sendbit(1'b0); for(i=0;i<8;i=i+1) sendbit(8'h07>>i & 1'b1 ? (8'h07>>i)&1 : 0); // placeholder
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t /app/dut.sv /tmp/tb.sv && vvp /tmp/t 2>&1 | grep -E '^\['[good] out=a5 done=1 count=1 ferr=0 perr=0 ovf=0 [ack] done=0 [ferr] count=1 ferr=1 done=0 [clr] ferr=0 [ovf] out=a5 count=1 ovf=0 done=0 [stdout] [good] out=a5 done=1 count=1 ferr=0 perr=0 ovf=0 [ack] done=0 [ferr] count=1 ferr=1 done=0 [clr] ferr=0 [ovf] out=a5 count=1 ovf=0 done=0
Test overflow, parity, 7N1, false-start
cat > /tmp/tb2.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1;
reg [2:0] frame_fmt_i=3'b000;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
task idle; begin in=1; repeat(48) @(posedge clk); end endtask
// generic frame: nbits data, optional parity bit, then high stop
task sendframe(input [7:0] data, input [3:0] nbits, input has_par, input par_bit);
begin sendbit(0); for(i=0;i<nbits;i=i+1) sendbit(data[i]);
if(has_par) sendbit(par_bit); sendbit(1); end
endtask
initial begin
repeat(3) @(posedge clk); reset=0; idle;
// ---- overflow: two good 8N1 frames, no ack ----
sendframe(8'h11,8,0,0); repeat(3) @(posedge clk); idle;
sendframe(8'h22,8,0,0); repeat(3) @(posedge clk);
$display("[ovf] out=%02x count=%0d ovf=%b done=%b (want out=22 count=2 ovf=1 done=1)",
out_byte,byte_count_o,ovf_o,done);
data_ack_i=1; @(posedge clk); data_ack_i=0; idle;
// ---- 8E1 correct parity: data 0x07 has 3 ones -> even parity bit=1 ----
frame_fmt_i=3'b010; sendframe(8'h07,8,1,1'b1); repeat(3) @(posedge clk);
$display("[8E1ok] out=%02x done=%b count=%0d perr=%b (want done=1 perr=0)",
out_byte,done,byte_count_o,parity_err_o);
// ---- 8E1 wrong parity: send wrong bit=0 ----
clear_err_i=1;@(posedge clk);clear_err_i=0; data_ack_i=1;@(posedge clk);data_ack_i=0; idle;
sendframe(8'h07,8,1,1'b0); repeat(3) @(posedge clk);
$display("[8Ebad] perr=%b done=%b count=%0d (want perr=1 done=0)",
parity_err_o,done,byte_count_o);
// ---- 7N1: out_byte[7] must be 0 ----
clear_err_i=1;@(posedge clk);clear_err_i=0; idle;
frame_fmt_i=3'b001; sendframe(8'h7F,7,0,0); repeat(3) @(posedge clk);
$display("[7N1] out=%02x done=%b (want out=7f, bit7=0)", out_byte,done);
// ---- false start: start goes high at midpoint ----
frame_fmt_i=3'b000; data_ack_i=1;@(posedge clk);data_ack_i=0; idle;
in=0; repeat(4) @(posedge clk); in=1; repeat(60) @(posedge clk);
$display("[false] done=%b ferr=%b perr=%b (want all 0 / no frame)",done,frame_err_o,parity_err_o);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t2 /app/dut.sv /tmp/tb2.sv && vvp /tmp/t2 2>&1 | grep -E '^\['[ovf] out=22 count=2 ovf=1 done=1 (want out=22 count=2 ovf=1 done=1) [8E1ok] out=07 done=1 count=3 perr=0 (want done=1 perr=0) [8Ebad] perr=1 done=1 count=3 (want perr=1 done=0) [7N1] out=7f done=1 (want out=7f, bit7=0) [false] done=0 ferr=0 perr=0 (want all 0 / no frame) [stdout] [ovf] out=22 count=2 ovf=1 done=1 (want out=22 count=2 ovf=1 done=1) [8E1ok] out=07 done=1 count=3 perr=0 (want done=1 perr=0) [8Ebad] perr=1 done=1 count=3 (want perr=1 done=0) [7N1] out=7f done=1 (want out=7f, bit7=0) [false] done=0 ferr=0 perr=0 (want all 0 / no frame)
Isolate done-clear and bad-parity behavior
cat > /tmp/tb3.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b010;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
task idle; begin in=1; repeat(48) @(posedge clk); end endtask
initial begin
repeat(3) @(posedge clk); reset=0; idle;
// good 8E1 (0x07, parity=1)
sendbit(0); for(i=0;i<8;i=i+1) sendbit(8'h07[i]); sendbit(1'b1); sendbit(1);
repeat(3) @(posedge clk); $display("after good: done=%b",done);
data_ack_i=1; @(posedge clk); data_ack_i=0; @(posedge clk);
$display("after ack: done=%b (want 0)",done);
idle;
// bad 8E1 (0x07, parity=0 wrong)
sendbit(0); for(i=0;i<8;i=i+1) sendbit(8'h07[i]); sendbit(1'b0); sendbit(1);
repeat(3) @(posedge clk);
$display("after bad: done=%b perr=%b count=%0d (want done=0 perr=1)",done,parity_err_o,byte_count_o);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t3 /app/dut.sv /tmp/tb3.sv && vvp /tmp/t3 2>&1 | grep -E 'after'Exit code 4 /tmp/tb3.sv:17: syntax error /tmp/tb3.sv:17: error: Syntax error in task arguments. /tmp/tb3.sv:23: syntax error /tmp/tb3.sv:23: error: Syntax error in task arguments. [error] tool reported failure
Isolate done-clear and bad-parity behavior
cat > /tmp/tb3.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b010;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i; reg [7:0] dat=8'h07;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
task idle; begin in=1; repeat(48) @(posedge clk); end endtask
initial begin
repeat(3) @(posedge clk); reset=0; idle;
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]); sendbit(1'b1); sendbit(1);
repeat(3) @(posedge clk); $display("after good: done=%b",done);
data_ack_i=1; @(posedge clk); data_ack_i=0; @(posedge clk);
$display("after ack: done=%b (want 0)",done);
idle;
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]); sendbit(1'b0); sendbit(1);
repeat(3) @(posedge clk);
$display("after bad: done=%b perr=%b count=%0d (want done=0 perr=1)",done,parity_err_o,byte_count_o);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t3 /app/dut.sv /tmp/tb3.sv && vvp /tmp/t3 2>&1 | grep -E 'after'after good: done=1 after ack: done=0 (want 0) after bad: done=0 perr=1 count=1 (want done=0 perr=1) [stdout] after good: done=1 after ack: done=0 (want 0) after bad: done=0 perr=1 count=1 (want done=0 perr=1)
Diagnose done-clear plus break detection
cat > /tmp/tb4.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b010;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i; reg [7:0] dat=8'h07;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
task idle; begin in=1; repeat(48) @(posedge clk); end endtask
initial begin
repeat(3) @(posedge clk); reset=0; idle;
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]); sendbit(1'b1); sendbit(1);
repeat(3) @(posedge clk); $display("[ok] done=%b count=%0d",done,byte_count_o);
clear_err_i=1;@(posedge clk);clear_err_i=0; data_ack_i=1;@(posedge clk);data_ack_i=0;
@(posedge clk); $display("[after ack] done=%b",done);
idle;
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]); sendbit(1'b0); sendbit(1);
repeat(3) @(posedge clk);
$display("[bad] done=%b perr=%b count=%0d",done,parity_err_o,byte_count_o);
// ---- break test: hold low > 11 bit-times (11*16=176 clocks @ baud=1) ----
idle;
in=0; repeat(200) @(posedge clk);
$display("[brk lo] break=%b (want 1)", break_o);
in=1; @(posedge clk);
$display("[brk hi+1] break=%b (want 0)", break_o);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t4 /app/dut.sv /tmp/tb4.sv && vvp /tmp/t4 2>&1 | grep -E '^\['[ok] done=1 count=1 [after ack] done=1 [bad] done=1 perr=1 count=1 [brk lo] break=1 (want 1) [brk hi+1] break=1 (want 0) [stdout] [ok] done=1 count=1 [after ack] done=1 [bad] done=1 perr=1 count=1 [brk lo] break=1 (want 1) [brk hi+1] break=1 (want 0)
Recheck done-clear and break with settle cycles
cat > /tmp/tb5.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b010;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i; reg [7:0] dat=8'h07;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
task idle; begin in=1; repeat(48) @(posedge clk); end endtask
initial begin
repeat(3) @(posedge clk); reset=0; idle;
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]); sendbit(1'b1); sendbit(1);
repeat(2) @(posedge clk); $display("[ok] done=%b",done);
// ack with settle time
data_ack_i=1; @(posedge clk); data_ack_i=0;
@(posedge clk); $display("[after ack] done=%b (want 0)",done);
idle;
// break: hold low long, then release, check with settle
in=0; repeat(200) @(posedge clk);
$display("[brk lo] break=%b (want 1)", break_o);
in=1; @(posedge clk); @(posedge clk);
$display("[brk hi] break=%b (want 0)", break_o);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t5 /app/dut.sv /tmp/tb5.sv && vvp /tmp/t5 2>&1 | grep -E '^\['[ok] done=1 [after ack] done=1 (want 0) [brk lo] break=1 (want 1) [brk hi] break=0 (want 0) [stdout] [ok] done=1 [after ack] done=1 (want 0) [brk lo] break=1 (want 1) [brk hi] break=0 (want 0)
Per-cycle dump around commit and ack
cat > /tmp/tb6.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b000; // 8N1 simpler
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i; reg [7:0] dat=8'h55; reg mon=0;
task sendbit(input b); integer k; begin in=b; for(k=0;k<16;k=k+1) @(posedge clk); end endtask
always @(posedge clk) if(mon)
$display("t=%0t state=%0d cnt=%0d done=%b ack=%b cmt=%b done_next", $time,
d.state, d.clk_cnt, done, data_ack_i, d.commit);
initial begin
repeat(3) @(posedge clk); reset=0; in=1; repeat(4) @(posedge clk);
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]);
mon=1; sendbit(1); // stop bit - monitor this window
repeat(2) @(posedge clk);
data_ack_i=1; @(posedge clk); data_ack_i=0;
@(posedge clk); mon=0;
$display("[after ack] done=%b (want 0)",done);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t6 /app/dut.sv /tmp/tb6.sv && vvp /tmp/t6 2>&1 | grep -E 'state=4|after|cmt=1't=1515 state=4 cnt=0 done=0 ack=0 cmt=0 done_next t=1525 state=4 cnt=1 done=0 ack=0 cmt=0 done_next t=1535 state=4 cnt=2 done=0 ack=0 cmt=0 done_next t=1545 state=4 cnt=3 done=0 ack=0 cmt=0 done_next t=1555 state=4 cnt=4 done=0 ack=0 cmt=0 done_next t=1565 state=4 cnt=5 done=0 ack=0 cmt=0 done_next t=1575 state=4 cnt=6 done=0 ack=0 cmt=0 done_next t=1585 state=4 cnt=7 done=0 ack=0 cmt=0 done_next t=1595 state=4 cnt=8 done=0 ack=0 cmt=0 done_next t=1605 state=4 cnt=9 done=0 ack=0 cmt=0 done_next t=1615 state=4 cnt=10 done=0 ack=0 cmt=0 done_next t=1625 state=4 cnt=11 done=0 ack=0 cmt=0 done_next t=1635 state=4 cnt=12 done=0 ack=0 cmt=0 done_next t=1645 state=4 cnt=13 done=0 ack=0 cmt=0 done_next t=1655 state=4 cnt=14 done=0 ack=0 cmt=0 done_next t=1665 state=4 cnt=15 done=0 ack=0 cmt=1 done_next [after ack] done=1 (want 0) [stdout] t=1515 state=4 cnt=0 done=0 ack=0 cmt=0 done_next t=1525 state=4 cnt=1 done=0 ack=0 cmt=0 done_next t=1535 state=4 cnt=2 done=0 ack=0 cmt=0 done_next t=1545 state=4 cnt=3 done=0 ack=0 cmt=0 done_next t=1555 state=4 cnt=4 done=0 ack=0 cmt=0 done_next t=1565 state=4 cnt=5 done=0 ack=0 cmt=0 done_next t=1575 state=4 cnt=6 done=0 ack=0 cmt=0 done_next t=1585 state=4 cnt=7 done=0 ack=0 cmt=0 done_next t=1595 state=4 cnt=8 done=0 ack=0 cmt=0 done_next t=1605 state=4 cnt=9 done=0 ack=0 cmt=0 done_next t=1615 state=4 cnt=10 done=0 ack=0 cmt=0 done_next t=1625 state=4 cnt=11 done=0 ack=0 cmt=0 done_next t=1635 state=4 cnt=12 done=0 ack=0 cmt=0 done_next t=1645 state=4 cnt=13 done=0 ack=0 cmt=0 done_next t=1655 state=4 cnt=14 done=0 ack=0 cmt=0 done_next t=1665 state=4 cnt=15 done=0 ack=0 cmt=1 done_next [after ack] done=1 (want 0)
Show commit-through-ack window unfiltered
vvp /tmp/t6 2>&1 | grep -vE 'state=4 cnt=([0-9]|1[0-4]) '
t=1665 state=4 cnt=15 done=0 ack=0 cmt=1 done_next t=1675 state=0 cnt=0 done=1 ack=0 cmt=0 done_next t=1685 state=0 cnt=0 done=1 ack=0 cmt=0 done_next t=1695 state=0 cnt=0 done=1 ack=0 cmt=0 done_next t=1705 state=0 cnt=0 done=1 ack=0 cmt=0 done_next [after ack] done=1 (want 0) /tmp/tb6.sv:24: $finish called at 1705 (1s) [stdout] t=1665 state=4 cnt=15 done=0 ack=0 cmt=1 done_next t=1675 state=0 cnt=0 done=1 ack=0 cmt=0 done_next t=1685 state=0 cnt=0 done=1 ack=0 cmt=0 done_next t=1695 state=0 cnt=0 done=1 ack=0 cmt=0 done_next t=1705 state=0 cnt=0 done=1 ack=0 cmt=0 done_next [after ack] done=1 (want 0) /tmp/tb6.sv:24: $finish called at 1705 (1s)
Retest done-clear with negedge-driven stimulus
cat > /tmp/tb7.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b000;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i; reg [7:0] dat=8'h55;
// drive stimulus on negedge to avoid posedge races; sample on negedge too
task sendbit(input b); integer k; begin @(negedge clk) in=b; for(k=0;k<15;k=k+1) @(negedge clk); end endtask
initial begin
@(negedge clk) reset=1; repeat(2)@(negedge clk); reset=0; in=1; repeat(4)@(negedge clk);
sendbit(0); for(i=0;i<8;i=i+1) sendbit(dat[i]); sendbit(1);
repeat(3)@(negedge clk); $display("[ok] done=%b out=%02x count=%0d",done,out_byte,byte_count_o);
@(negedge clk) data_ack_i=1; @(negedge clk) data_ack_i=0;
repeat(2)@(negedge clk); $display("[after ack] done=%b (want 0)",done);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/t7 /app/dut.sv /tmp/tb7.sv && vvp /tmp/t7 2>&1 | grep -E '^\['[ok] done=1 out=55 count=1 [after ack] done=0 (want 0) [stdout] [ok] done=1 out=55 count=1 [after ack] done=0 (want 0)
Full comprehensive UART test suite
cat > /tmp/tbf.sv <<'EOF'
module tb;
reg clk=0, reset=1, in=1, clear_err_i=0, data_ack_i=0;
reg [15:0] baud_div_i=1; reg [2:0] frame_fmt_i=3'b000;
wire [7:0] out_byte; wire done,parity_err_o,frame_err_o,break_o,ovf_o;
wire [7:0] byte_count_o;
TopModule d(.clk(clk),.reset(reset),.in(in),.baud_div_i(baud_div_i),
.frame_fmt_i(frame_fmt_i),.clear_err_i(clear_err_i),.data_ack_i(data_ack_i),
.out_byte(out_byte),.done(done),.parity_err_o(parity_err_o),
.frame_err_o(frame_err_o),.break_o(break_o),.ovf_o(ovf_o),.byte_count_o(byte_count_o));
always #5 clk=~clk;
integer i; integer pass=0, fail=0;
reg [15:0] BW=16; // 16 clocks/bit (baud=1)
task sendbit(input b); integer k; begin @(negedge clk) in=b; for(k=0;k<BW-1;k=k+1)@(negedge clk); end endtask
task idle; begin @(negedge clk) in=1; repeat(3*BW)@(negedge clk); end endtask
task ack; begin @(negedge clk) data_ack_i=1; @(negedge clk) data_ack_i=0; end endtask
task clr; begin @(negedge clk) clear_err_i=1; @(negedge clk) clear_err_i=0; end endtask
// frame with explicit parity + one high stop
task fr(input [7:0] d, input [3:0] n, input hp, input pb, input sb);
begin sendbit(0); for(i=0;i<n;i=i+1) sendbit(d[i]); if(hp) sendbit(pb); sendbit(sb);
repeat(3)@(negedge clk); end
endtask
task chk(input [127:0] nm, input c); begin
if(c) begin pass=pass+1; end
else begin fail=fail+1; $display("FAIL: %0s",nm); end end
endtask
initial begin
@(negedge clk) reset=1; repeat(2)@(negedge clk); reset=0; idle;
// 1) good 8N1
frame_fmt_i=3'b000; fr(8'hA5,8,0,0,1);
chk("8N1 byte",out_byte==8'hA5); chk("8N1 done",done==1); chk("8N1 cnt",byte_count_o==1);
chk("8N1 noerr",{parity_err_o,frame_err_o,ovf_o}==0);
ack; @(negedge clk); chk("ack clears done",done==0); idle;
// 2) 7N1 -> bit7=0
frame_fmt_i=3'b001; fr(8'hFF,7,0,0,1);
chk("7N1 byte",out_byte==8'h7F); chk("7N1 done",done==1); ack; idle;
// 3) 8E1 good: 0x07 (3 ones) parity=1
frame_fmt_i=3'b010; fr(8'h07,8,1,1,1);
chk("8E1 ok byte",out_byte==8'h07); chk("8E1 ok done",done==1); chk("8E1 ok noperr",parity_err_o==0);
ack; idle;
// 4) 8E1 bad parity: send 0
frame_fmt_i=3'b010; fr(8'h07,8,1,0,1);
chk("8E1 bad perr",parity_err_o==1); chk("8E1 bad nodone",done==0); chk("8E1 bad nocnt",byte_count_o==2);
clr; chk("clr perr",parity_err_o==0); idle;
// 5) 8O1 good: 0x07 (3 ones, odd) parity=0
frame_fmt_i=3'b011; fr(8'h07,8,1,0,1);
chk("8O1 ok done",done==1); chk("8O1 ok noperr",parity_err_o==0); ack; idle;
// 6) framing error: low stop
frame_fmt_i=3'b000; fr(8'h3C,8,0,0,0);
chk("ferr set",frame_err_o==1); chk("ferr nodone",done==0); chk("ferr nocnt",byte_count_o==3);
clr; idle;
// 7) 8N2 good (two stops)
frame_fmt_i=3'b100; sendbit(0); for(i=0;i<8;i=i+1) sendbit(8'hC3>>0 & 0 ? 0:(8'hC3>>i)&1);
sendbit(1); sendbit(1); repeat(3)@(negedge clk);
chk("8N2 byte",out_byte==8'hC3); chk("8N2 done",done==1); ack; idle;
// 8) 8N2 framing err on 2nd stop only, still consumes slot
frame_fmt_i=3'b100; sendbit(0); for(i=0;i<8;i=i+1) sendbit((8'h81>>i)&1);
sendbit(1); sendbit(0); repeat(3)@(negedge clk);
chk("8N2 ferr",frame_err_o==1); chk("8N2 ferr nodone",done==0); clr; idle;
// 9) overflow: two good frames no ack
frame_fmt_i=3'b000; fr(8'h11,8,0,0,1);
frame_fmt_i=3'b000; fr(8'h22,8,0,0,1);
chk("ovf set",ovf_o==1); chk("ovf byte replaced",out_byte==8'h22); chk("ovf still done",done==1);
ack; clr; idle;
// 10) false start: start high at midpoint
frame_fmt_i=3'b000; @(negedge clk) in=0; repeat(4)@(negedge clk); in=1; repeat(2*BW)@(negedge clk);
chk("false no done",done==0); chk("false no ferr",frame_err_o==0);
// 11) break: hold low > 11 bit times
baud_div_i=1; @(negedge clk) in=0; repeat(12*BW)@(negedge clk);
chk("break asserts",break_o==1);
@(negedge clk) in=1; @(negedge clk); @(negedge clk);
chk("break deasserts",break_o==0);
reset=1; @(negedge clk) reset=0; idle;
// 12) baud=0 latched as 1 -> normal frame with baud_div_i=0
baud_div_i=0; BW=16; frame_fmt_i=3'b000; fr(8'h5A,8,0,0,1);
chk("baud0->1 byte",out_byte==8'h5A); chk("baud0->1 done",done==1);
$display("RESULT pass=%0d fail=%0d", pass, fail);
$finish;
end
endmodule
EOF
iverilog -g2012 -o /tmp/tf /app/dut.sv /tmp/tbf.sv && vvp /tmp/tf 2>&1 | grep -E 'FAIL|RESULT'FAIL: 8E1 bad nocnt FAIL: ferr nocnt RESULT pass=30 fail=2 [stdout] FAIL: 8E1 bad nocnt FAIL: ferr nocnt RESULT pass=30 fail=2
Rerun suite with corrected count expectations
sed -i 's/chk("8E1 bad nocnt",byte_count_o==2)/chk("8E1 bad nocnt",byte_count_o==3)/; s/chk("ferr nocnt",byte_count_o==3)/chk("ferr nocnt",byte_count_o==4)/' /tmp/tbf.sv
iverilog -g2012 -o /tmp/tf /app/dut.sv /tmp/tbf.sv && vvp /tmp/tf 2>&1 | grep -E 'FAIL|RESULT'RESULT pass=32 fail=0 [stdout] RESULT pass=32 fail=0
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 harness_prepare: PASS (harness names nonce-renamed) TEST dut_compiles: PASS (compiled with held-back reference/testbench) TEST simulation_completed: PASS (Mismatches: 6716 in 155243 samples) TEST reference_equivalence: FAIL (6716 mismatches in 155243 samples)
Reproduce this trial: git checkout 2f94510 && PYTHONPATH=src python3 scripts/build_site.py , then open trial/trial_1fff9026429c4e57. Re-running the agent live requires EVAL_PLATFORM_ENABLE_OAUTH_SMOKE=1 and is non-deterministic.
Trial trial_1fff9026429c4e57 · verifier authoritative; classifier explanatory.