I'm trying to write a simple counter using Verilog on Quartus Prime and a testbench in Verilog being tested with Questa FPGA modelSim.
The goal of my counter is to count up to 7 at positive edge of a clock cycle and wrap back to 0 after 7 or if the low assert reset signal is asserted.
I am getting the counting and the wrapping after 7 correct; however, the counter does not wrap back when the reset is asserted.
Module
// TFT_LCD_Driver Second Version
module TFT_LCD_Driver(
input clk,
input rst_n,
output reg [3:0] cnt
);
initial cnt = 0;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt <= 0;
if (cnt == 4'd7)
cnt <= 0;
else
cnt <= cnt + 4'd1;
end
endmodule
TestBench
// TFT_LCD_Driver_tb
// spi driver test bench
`define clk_period 20
module TFT_LCD_Driver_tb();
reg clk;
reg rst_n;
wire [3:0] cnt;
TFT_LCD_Driver tft(
.clk(clk),
.rst_n(rst_n),
.cnt(cnt)
);
initial begin
clk = 1'b1;
rst_n = 1'b1;
#30 rst_n = 1'b0;
#30 rst_n = 1'b1;
end
always #(`clk_period/2) clk = ~clk;
endmodule
Here is waveform of the incorrect counter
I expect to see that the counter goes to 0 when the low assert reset signal is pulled low. However, the waveform shows that it continues to count until 7 and then wraps back to 0. I have highlighted and marked the incorrect spot where I expect the restart.
You have 2 separate if
statements in your always
block. The 2nd one takes precedence over the 1st. Just before reset is asserted, cnt
is 2. The 1st assignment does not take effect, but the increment assignment does take effect, setting cnt
to 3.
You should change:
if (cnt == 4'd7)
to:
else if (cnt == 4'd7)
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
cnt <= 0;
else if (cnt == 4'd7)
cnt <= 0;
else
cnt <= cnt + 4'd1;
end