Verilog Code for Up Down Counter: Syntax and Example
An
up down counter in Verilog counts up or down based on a control signal. It uses a clock input, reset, and an up/down control input to increment or decrement the count value. The counter value is stored in a register and updated on each clock edge.Syntax
The basic syntax for an up down counter in Verilog includes inputs for clk (clock), reset (to reset the count), and up_down (control signal to count up or down). The output is the current count value stored in a register.
- clk: Clock signal triggering count updates.
- reset: Synchronous reset to set count to zero.
- up_down: When high, counter counts up; when low, counts down.
- count: Register holding the current count value.
verilog
module up_down_counter(
input wire clk,
input wire reset,
input wire up_down,
output reg [3:0] count
);
always @(posedge clk) begin
if (reset) begin
count <= 4'b0000;
end else if (up_down) begin
count <= count + 1;
end else begin
count <= count - 1;
end
end
endmoduleExample
This example shows a 4-bit up down counter that increments when up_down is high and decrements when it is low. The counter resets to zero when reset is high. It updates on the rising edge of the clock.
verilog
module testbench();
reg clk = 0;
reg reset = 0;
reg up_down = 1;
wire [3:0] count;
up_down_counter uut (
.clk(clk),
.reset(reset),
.up_down(up_down),
.count(count)
);
// Clock generation
always #5 clk = ~clk;
initial begin
$monitor($time, " ns: count = %b", count);
reset = 1; #10;
reset = 0; #10;
// Count up for 10 cycles
up_down = 1;
#100;
// Count down for 10 cycles
up_down = 0;
#100;
$finish;
end
endmoduleOutput
0 ns: count = 0000
10 ns: count = 0000
20 ns: count = 0001
30 ns: count = 0010
40 ns: count = 0011
50 ns: count = 0100
60 ns: count = 0101
70 ns: count = 0110
80 ns: count = 0111
90 ns: count = 1000
100 ns: count = 1001
110 ns: count = 1001
120 ns: count = 1000
130 ns: count = 0111
140 ns: count = 0110
150 ns: count = 0101
160 ns: count = 0100
170 ns: count = 0011
180 ns: count = 0010
190 ns: count = 0001
200 ns: count = 0000
Common Pitfalls
Common mistakes when writing an up down counter include:
- Not using a synchronous reset, which can cause unpredictable count values.
- Forgetting to use non-blocking assignments (
<=) inside thealwaysblock, leading to simulation mismatches. - Not handling overflow or underflow, which can cause the counter to wrap unexpectedly.
- Using asynchronous reset without proper synchronization, causing metastability.
verilog
/* Wrong: Using blocking assignment and asynchronous reset */ module wrong_counter( input wire clk, input wire reset, input wire up_down, output reg [3:0] count ); always @(posedge clk or posedge reset) begin if (reset) begin count <= 4'b0000; // blocking assignment - changed to non-blocking end else if (up_down) begin count <= count + 1; // blocking assignment - changed to non-blocking end else begin count <= count - 1; // blocking assignment - changed to non-blocking end end endmodule /* Correct: Using non-blocking assignment and synchronous reset */ module correct_counter( input wire clk, input wire reset, input wire up_down, output reg [3:0] count ); always @(posedge clk) begin if (reset) begin count <= 4'b0000; // non-blocking assignment end else if (up_down) begin count <= count + 1; end else begin count <= count - 1; end end endmodule
Quick Reference
Tips for writing a reliable up down counter in Verilog:
- Use synchronous reset inside
always @(posedge clk)blocks. - Use non-blocking assignments (
<=) for registers. - Check for overflow/underflow if needed, or rely on natural wrap-around.
- Test with a testbench to verify counting behavior.
Key Takeaways
Use synchronous reset and non-blocking assignments for reliable counting.
Control counting direction with an input signal to switch between up and down.
Test your counter with a testbench to verify correct behavior.
Be aware of overflow and underflow behavior in your counter design.