This time I am going to design a simple counter circuit. This will build on concepts from the earlier sequential circuit design project. To keep this project simple this be only a 4-bit counter. We may want the ability to reset the counter, so in addition to the clk port I will define another input port called rst. And we need an output port for the 4-bit counter value. For that I will define a 4-bit output port q[3:0]. The output should remain the same until the next clk transition, so our counter will need to be of reg type.
Since our circuit needs to respond to both the clk and rst signals I use an always block with appropriate sensitivities. Within our always block we will use a non-blocking assignment to update our count. If you don’t recall how the non-blocking assignment operator ‘<=‘ works you may want to review the earlier post on sequential cirtcuits. When the rst signal is raised, we want the counter to reset to zero. And we want our count to increment each time the clk signal is raised. Let’s see how that all looks in Verilog.
module counter(
input clk,
input rst,
output [3:0] q
);
// counter register
reg [3:0] rCounter;
// increment or reset the counter
always @(posedge clk, posedge rst)
if (rst)
rCounter <= 0;
else
rCounter <= rCounter + 1;
// connect counter register to the output wires
assign q = rCounter;
endmodule
There is one new construct in this code that we haven’t seen previously. And that is the if-else statement. Similar to software programming languages, Verilog provides an if statement to allow for conditional logic. If the rst signal is asserted (logic 1), then it evaluates one set of statements, else it evaluates another set of statements. However, rather than branching to a different code path, with an FPGA we are selecting which output to use. In hardware terms an if statement infers a priority routing network. A single if-else infers a 2:1 multiplexer (MUX).
But does it work? To see if it does, I run this in Vivado’s Behavioral Simulation. From the resulting waveform we can observe a few things. At the very beginning of the simulation I raise the rst signal and the count is zero. Once rst is logic 0 the counter begins to count up on each clk tick. When I raise rst again it once again starts counting from zero. Note that at 400ns the output q wraps from 15 (hex value f) back to zero.
And there it is! A 4-bit counter circuit with asynchronous reset. It would not be difficult to add an output signal that is raised each time the count wraps. And it would also be nice to configure the number of bits to avoid many different trivial copies of this design. Those are some good ideas for the future.
The source code is available on github. If you have comments, questions or suggestions, please leave me a comment!