Added timer, still wip

This commit is contained in:
2026-02-25 20:54:12 +01:00
parent f2f9644830
commit 3a3c951409
12 changed files with 768 additions and 203 deletions

45
sim/tb/tb_top_generic.v Normal file
View File

@@ -0,0 +1,45 @@
`timescale 1ns/1ps
module tb_top_generic();
reg aclk;
reg aresetn;
wire led_green;
wire led_red;
wire [5:0] r2r;
wire [7:0] LED;
// 100 MHz board input clock
initial aclk = 1'b0;
always #5 aclk = ~aclk;
// Hold reset low, then release
initial begin
aresetn = 1'b0;
#200;
aresetn = 1'b1;
end
top_generic #(
.sim(1)
) dut (
.aclk(aclk),
.aresetn(aresetn),
.led_green(led_green),
.led_red(led_red),
.r2r(r2r),
.LED(LED)
);
// Ensure firmware path resolves from repository root when simulating.
defparam dut.mcu.memfile = "sw/sweep/sweep.hex";
initial begin
$dumpfile("out.vcd");
$dumpvars(0, tb_top_generic);
// Let firmware run for a while.
#5_000_000;
$finish;
end
endmodule

157
sim/tb/tb_wb_timer.v Normal file
View File

@@ -0,0 +1,157 @@
`timescale 1ns/1ps
module tb_wb_timer();
localparam integer CLK_HALF_NS = 5;
reg clk;
reg rst;
reg [31:0] i_wb_dat;
wire [31:0] o_wb_dat;
reg i_wb_we;
reg i_wb_cyc;
reg i_wb_stb;
wire o_wb_ack;
wire o_irq;
integer errors;
wb_countdown_timer #(
.WIDTH(8),
.DIVIDER(0)
) dut (
.i_clk (clk),
.i_rst (rst),
.o_irq (o_irq),
.i_wb_dat(i_wb_dat),
.o_wb_dat(o_wb_dat),
.i_wb_we (i_wb_we),
.i_wb_cyc(i_wb_cyc),
.i_wb_stb(i_wb_stb),
.o_wb_ack(o_wb_ack)
);
always #CLK_HALF_NS clk = ~clk;
task wb_write;
input [31:0] data;
begin
@(negedge clk);
i_wb_dat = data;
i_wb_we = 1'b1;
i_wb_cyc = 1'b1;
i_wb_stb = 1'b1;
#1;
if (!o_wb_ack) begin
$display("FAIL: WB write ACK not asserted when cyc/stb high");
errors = errors + 1;
end
@(negedge clk);
i_wb_we = 1'b0;
i_wb_cyc = 1'b0;
i_wb_stb = 1'b0;
end
endtask
task wb_read_check;
input [31:0] expected;
begin
@(negedge clk);
i_wb_we = 1'b0;
i_wb_cyc = 1'b1;
i_wb_stb = 1'b1;
#1;
if (!o_wb_ack) begin
$display("FAIL: WB read ACK not asserted when cyc/stb high");
errors = errors + 1;
end
if (o_wb_dat !== expected) begin
$display("FAIL: WB read mismatch. got=0x%08h expected=0x%08h", o_wb_dat, expected);
errors = errors + 1;
end
@(negedge clk);
i_wb_cyc = 1'b0;
i_wb_stb = 1'b0;
end
endtask
task wait_irq_with_timeout;
input integer max_cycles;
integer k;
begin
k = 0;
while ((o_irq !== 1'b1) && (k < max_cycles)) begin
@(posedge clk);
k = k + 1;
end
if (o_irq !== 1'b1) begin
$display("FAIL: IRQ did not assert within %0d cycles", max_cycles);
errors = errors + 1;
end
end
endtask
initial begin
$dumpfile("out.vcd");
$dumpvars;
clk = 1'b0;
rst = 1'b1;
i_wb_dat = 32'd0;
i_wb_we = 1'b0;
i_wb_cyc = 1'b0;
i_wb_stb = 1'b0;
errors = 0;
$display("---------------------------------------");
$display("Testbench: wb_countdown_timer");
$display("---------------------------------------");
repeat (3) @(posedge clk);
rst = 1'b0;
repeat (1) @(posedge clk);
if (o_irq !== 1'b0) begin
$display("FAIL: IRQ should be low after reset");
errors = errors + 1;
end
wb_read_check(32'd0);
// Load timer and check readback at a deterministic point
wb_write(32'd5);
@(posedge clk);
wb_read_check(32'd4);
// Wait until expiration, then verify sticky IRQ behavior
wait_irq_with_timeout(6);
wb_read_check(32'd0);
repeat (2) @(posedge clk);
if (o_irq !== 1'b1) begin
$display("FAIL: IRQ should remain sticky until next write");
errors = errors + 1;
end
// A new write must clear IRQ and restart the counter
wb_write(32'd2);
if (o_irq !== 1'b0) begin
$display("FAIL: IRQ should clear on write");
errors = errors + 1;
end
wait_irq_with_timeout(3);
if (errors == 0)
$display("PASS: wb_timer basic functionality verified");
else
$display("FAIL: wb_timer testbench found %0d error(s)", errors);
$finish;
end
endmodule