A lot of interesting things can be built by combining arithmetic circuits and sequential elements. In this project, we are going to provide arithmetic circuits with timing references by integrating arithmetic circuits with flip-flops. In the first part, we are going to use an adder with a register file (an array of flip-flops) to implement a counter that increases the number by 1 when the rising edge of the clock arrives. In the second part, we are going to revisit clock dividers. We will then implement a clock divider whose frequency can be more precisely calculated compared to the clock divider implemented in the previous projects.
|1||Digilent Nexys™4, Nexys™3, Nexys™2, or Basys™2 FPGA Board|
|1||Xilinx ISE Design Suite: WebPACK (14.6 Recommended)|
A counter is no more than an adder with a flip-flop for each of the output bits. The block diagram of a counter is shown below in Fig. 1.
When reset signal “rst” is asserted, the outputs of the counter (Q[7:0]) are 0. The outputs of flip-flops feed back to the input of the ripple-carry adder and present $0+1=1$ at the input of the flip-flops. When the reset signal is de-asserted, the outputs turn to 1 after the rising edge of the clock arrives. And $1+1=2$ will be presented at the inputs of the flip-flops. After the second rising edge of the clock arrives, 2 will show up on the outputs of the counter. As a result of the analysis, the flip-flops provide a timing reference (clock) to the adder so that the output of the counter is increased by 1 every time the rising edge of clock arrives.
To describe the circuit structurally in Verilog, you can use the RCA and the flip-flops you implemented in previous projects. Actually, it is a lot easier to code it behaviorally. To describe any sequential circuit, we can use the similar always block as the one we used to describe a D flip-flop. To implement the counter behaviorally, there are three statements we need to make:
So, the code for a counter is shown as follows:
module counter( input clk, input rst, output reg [7:0] Q ); always @ (posedge(clk), posedge(rst)) // When will Always Block Be Triggered begin if (rst == 1'b1) // How Output reacts when Reset Is Asserted Q <= 8'b0; else // How Output reacts when Rising Edge of Clock Arrives? Q <= Q + 1'b1; end endmodule
In the previous project, we explained how to use a flip-flop with an inverter to implement a clock divider that divides the frequency in half. In this section, we can use a counter with a comparator to condition a flip-flop with an inverter to implement a clock divider that can control the output frequency more precisely. The block diagram of such a clock divider is shown in Fig. 2.
In the block diagram, the counter increases by 1 whenever the rising edge of clk arrives. It also resets its output to '0' when it reaches the constant number defined in the constant block. The comparator compares the output of the counter with the pre-defined constant and asserts EQ if the output of counter is equal to the pre-defined constant. When EQ is asserted, the output of the clock divider flips.
Let's assume that the pre-defined number is 3, and the output of clock divider (clk_div) is initialized to 0. It takes three clock cycles before the output of the counter equals the pre-defined constant, 3. When it reaches 3, the output of clock divider (clk_div) turns to 1, and the counter resets itself. It takes another three cycles before the output of the counter equals the pre-defined constant, 3. When it reaches 3 again, clk_div turns back to 0. So it takes 6 clock cycles before clk_div goes to 1 and returns to 0 again. As a result, the frequency of clk_div is one sixth of the frequency of original clk.
In this example, we are going to use this clock divider to implement a signal of exactly 1 Hz frequency. First, we will need to calculate the constant. As an example, the input clock frequency of the Nexys3 is 100 MHz. We want our clk_div to be 1 Hz. So it should take 100000000 clock cycles before clk_div goes to '1' and returns to '0'. In another words, it takes 50000000 clock cycles for clk_div to flip its value. So the constant we need to choose here is 50000000. Now we will start to describe the circuit:
module ClkDivider ( input clk, input rst, output reg clk_div ); endmodule
localparam constantNumber = 50000000;
reg [31:0] count; always @ (posedge(clk), posedge(rst)) begin if (rst == 1'b1) count <= 32'b0; else if (count == constantNumber - 1) count <= 32'b0; else count <= count + 1; end
always @ (posedge(clk), posedge(rst)) begin if (rst == 1'b1) clk_div <= 1'b0; else if (count == constNumber - 1) clk_div <= ~clk_div; else clk_div <= clk_div; end
Now that you've completed this project, try these modifications: