Final project - Counter module
Code
`timescale 1ns/1ps
module counter #(parameter THRESHOLD = 16'b1111111111111111)(
input wire clk, // Clock
input wire rst_n, // Reset (active low)
input wire data_in, // data to count
output reg[15:0] data_cnt, // count
output wire finish // high when the counter reaches the threshold
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_cnt <= 0;
end
else if (data_in && data_cnt < THRESHOLD) begin
data_cnt <= data_cnt + 1;
end
end
assign finish = (data_cnt == THRESHOLD);
endmodule
Lint
verilator --lint-only -Wall -Ilib puf/counter.v
- V e r i l a t i o n R e p o r t: Verilator 5.044 2026-01-01 rev v5.044
- Verilator: Built from 0.031 MB sources in 2 modules, into 0.012 MB in 3 C++ files needing 0.000 MB
- Verilator: Walltime 0.005 s (elab=0.000, cvt=0.002, bld=0.000); cpu 0.005 s on 1 threads; alloced 30.344 MB
Test harness
`timescale 1ns/1ps
module test_counter;
// Inputs are reg (we drive them)
reg clk, rst_n, data_in;
// Outputs are wire (DUT drives them)
wire[15:0] data_cnt;
wire finish;
// Instantiate Device Under Test with a threshold value of 2
counter #(.THRESHOLD(2'b10)) myCounter (
.clk(clk),
.rst_n(rst_n),
.data_in(data_in),
.data_cnt(data_cnt),
.finish(finish)
);
// Clock generation
always #10 clk = ~clk; // 50 MHz (20ns period)
// Test stimulus
initial begin
$dumpfile("waves.vcd");
$dumpvars(0, test_counter);
// Initialize
$display("Initialize");
#10
clk = 0;
display;
// Reset
$display("----------- Reset --------------");
rst_n = 0;
data_in = 0;
#20
rst_n = 1;
#20
$display("----------------- --------------");
// Test case 1
$display("==> Test case 1: feed 3 items, it should stop counting after two");
data_in = 1;
#10
data_in = 0;
#10
data_in = 1;
#10
data_in = 0;
#10
data_in = 1;
#10
data_in = 0;
#10
display;
// Reset
$display(" --------- Reset --------------");
rst_n = 0;
data_in = 0;
#20
rst_n = 1;
#20
$display("----------------- --------------");
// Test case 2
$display("==> Test case 2: feed 1 item, it should not finish");
data_in = 1;
#10
data_in = 0;
#10
display;
$display("==> Feed one more.. it should finish since the threshold is set at 2");
data_in = 1;
#10
data_in = 0;
#10
display;
$display("==> Feed one more.. it should ignore it");
data_in = 1;
#10
data_in = 0;
#10
display;
#100
$finish;
end
task display;
#1 $display("data_in:%0h, data_cnt:%0h, finish:%0h, reset:%0h",
data_in, data_cnt, finish, rst_n);
endtask
endmodule
Test run in simulation
Initialize
data_in:x, data_cnt:xxxx, finish:x, reset:x
----------- Reset --------------
----------------- --------------
==> Test case 1: feed 3 items, it should stop counting after two
data_in:0, data_cnt:2, finish:1, reset:1
--------- Reset --------------
----------------- --------------
==> Test case 2: feed 1 item, it should not finish
data_in:0, data_cnt:1, finish:0, reset:1
==> Feed one more.. it should finish since the threshold is set at 2
data_in:0, data_cnt:2, finish:1, reset:1
==> Feed one more.. it should ignore it
data_in:0, data_cnt:2, finish:1, reset:1
puf/test_counter.v:89: $finish called at 315000 (1ps)