====== Use Flip-flops to Build a Clock Divider ====== A flip-flop is an edge-triggered memory circuit. In this project, we will implement a flip-flop behaviorally using Verilog, and use several flip-flops to create a clock divider that blinks LEDs. \\ \\ Memory Circuits \\ ===== Prerequisites ==== * Have the Xilinx ISE WebPACK installed. * Set up your [[https://digilent.com/shop/boards-and-components/system-boards/fpga-boards/|FPGA board]]. * Be able to describe a digital circuit using logic operators. * Be able to write test bench and simulate circuits using ISim. * Be able to model and simulate a circuit delay. ==== Software ==== * Xilinx ISE WebPACK. * [[software:adept:start]] ==== Hardware ==== * Xilinx ISE compatible board such as [[programmable-logic:nexys-4:start]], [[programmable-logic:nexys-3:start]], [[programmable-logic:nexys-2:start]], [[programmable-logic:basys-3:start]], or [[programmable-logic:basys-2:start]] ---- ===== D Flip-flop (D-FF) ===== A D flip-flop (D-FF) is one of the most fundamental memory devices. A D-FF typically has three inputs: a data input that defines the next state, a timing control \\ input that tells the flip-flop exactly when to "memorize" the data input, and a reset input that can cause the memory to be reset to '0' regardless of the other two inputs (usually referred as asynchronous reset). Figure 1 below displays the block diagram for a D-FF. \\ \\ D Flip-flop (DFF) \\ {{ :learn:programmable-logic:tutorials:use-flip-flops-to-build-a-clock-divider:dff.png?direct |Figure 1. D-FF block diagram.}} ===== Procedure ===== ==== 1. Implement D-FF ==== In this step, we are going to implement a D-FF with asynchronous reset. As the block diagram in Fig. 1 shows, D flip-flops have three inputs: data input (D), clock input (//clk//), and asynchronous reset input (//rst//, active high), and one output: data //output// (Q). module dff( input D, input clk, input rst, output Q ); To describe the behavior of the flip-flop, we are going to use an "//always//" block. On the contrary to combinational circuits, the output of flip-flop changes when a rising edge or falling edge of clock occurs or the reset is asserted. In other words, output Q is sensitive to clock signal //clk// and reset signal //rst//. So we can describe the circuit as follows: always at rising edge of //clk// or rising of //rst//, if rst is asserted, Q is driven to logic '0', else Q is driven by D. In Verilog code: always @ (posedge(clk), posedge(rst)) begin if (rst == 1) Q <= 1'b0; else Q <= D; end So the final Verilog implementation of a D-FF looks as follows: `timescale 1ns / 1ps module dff( input D, input clk, input rst, output Q ); always @ (posedge(clk), posedge(rst)) begin if (rst == 1) Q <= 1'b0; else Q <= D; end endmodule ===== Clock Divider ===== A clock signal is needed in order for sequential circuits to function. Usually the clock signal comes from a crystal oscillator on-board. The oscillator used on Digilent FPGA boards usually ranges from 50 MHz to 100 MHz; however, some peripheral controllers do not need such a high frequency to operate. There is a simple circuit that can divide the clock frequency by half. The circuit is shown in Fig. 2 below: {{ :learn:programmable-logic:tutorials:use-flip-flops-to-build-a-clock-divider:clkdivider.png?direct |Figure 2. Clock divider circuit and waveform.}} Assume //clkdiv// is high initially. As //din// inverts the signal clkdiv, //din// is initially low. When the first rising edge of clock arrives, //clkdiv// is updated by the current //din// value and changes to '0'. As soon as the //clkdiv// changes to '0', //din// will be pulled up to logic '1' by the inverter. When the next rising edge of //clk// occurs, //clkdiv// will change to logic '1' and //din// will change back to '0' after the propagation delay of the inverter. The waveform of the circuit in Fig. 2 above is shown on the right. As a result, the period of //clkdiv// (the time between two adjacent rising edges) doubles the period of //clk// (i.e., the frequency of //clkdiv// is half of the //clk// frequency). With this circuit, we can actually divide the clock by cascading the previous circuit, as displayed in Fig. 3 below: {{ :learn:programmable-logic:tutorials:use-flip-flops-to-build-a-clock-divider:cascadeclockdivider.png?direct |Figure 3. Cascade clock divider.}} Each stage divided the frequency by 2. Suppose that the input clock frequency to the first stage is 100 MHz (1,000,000Hz). After the first stage, the frequency became $ \frac{100MHz}{2}\ = 50 MHz $. After the second stage, the frequency became $ \frac{100MHz}{2.2}\ = 25 MHz $. After n stage, the frequency became: $$ \frac{100MHz}{\underbrace{2\cdot 2 \cdot \ldots \cdot 2}_\text{n}} = \frac{100,000,000}{2^n}Hz $$ ==== 2. Implement the Clock Divider to Blink an LED ==== The block diagram of the clock divider is shown in Fig. 4. We name the internal wire out of the flip-flop //clkdiv// and the wire connecting to the input of D-FF din. The frequency of each //clkdiv// is shown in red. {{ :learn:programmable-logic:tutorials:use-flip-flops-to-build-a-clock-divider:clkdividerdiagram.png?direct |Figure 4. Block diagram of clock divider.}} In this diagram, we need two inputs: on-board clock input //clk//, and a push-button as reset signal //rst//. we have one output to blink an LED, so let's call it //led//. module clk_divider( input clk, input rst, output led ); We need to declare all the internal wires we are going to use. wire [26:0] din; wire [26:0] clkdiv; We need to instantiate 27 flip-flops with 27 inverters to divide the clock frequency by $2^27$ to 0.745Hz. To instantiate the first flip-flop with an inverter, the Verilog code should be as follows: dff dff_inst0 ( .clk(clk), .rst(rst), .D(din[0]), .Q(clkdiv[0]) ); For the rest 26 flip-flops, you can copy the code above 26 times and change the names of the internal wire each port will map to. However, we can also use generate statement with a //for// loop in Verilog to generate the code for us. By observing the block diagram shown above in Fig. 3, starting from the second flip-flop, //rst// port of D-FF is always connected to signal rst. If the port D is connected to signal //din[i]//, then //clk// port is connected to //clkdiv[i-1]// and Q port is connected to //clkdiv[i]//. So, we can generate the 26 D-FF as follows: genvar i; generate for (i = 1; i < 27; i=i+1) begin : dff_gen_label dff dff_inst ( .clk(clkdiv[i-1]), .rst(rst), .D(din[i]), .Q(clkdiv[i]) ); end endgenerate; We can use the same generate statement to instantiate 27 inverters, or by observing the connections, the bus //din// is actually the inverse of bus //clkdiv//. So, instead of writing the generate statement, we can simply write one assign statement as follows: assign din = ~clkdiv; Connect the output of the flip-flop in the final stage to //led//. assign led = clkdiv[26]; So the Verilog file of the design should be as follows: `timescale 1ns / 1ps module clk_divider( input clk, input rst, output led ); wire [26:0] din; wire [26:0] clkdiv; dff dff_inst0 ( .clk(clk), .rst(rst), .D(din[0]), .Q(clkdiv[0]) ); genvar i; generate for (i = 1; i < 27; i=i+1) begin : dff_gen_label dff dff_inst ( .clk(clkdiv[i-1]), .rst(rst), .D(din[i]), .Q(clkdiv[i]) ); end endgenerate; assign din = ~clkdiv; assign led = clkdiv[26]; endmodule ==== 3. Stimulate the Circuit, Implement, and Test it On-board ==== As with the combinational circuit we have designed in previous projects, you can draft a test bench to test the circuit out before implementing it on-chip. However, in this test bench, we need to emulate the clock signal and the rst signal. The clock signal is actually a constantly oscillating signal. Using the Nexys 3 as an example, the input clock frequency is 100 MHz, i.e., the period of the clock is 10 ns. Half of the period the clock is high, half of the period clock is low. In other words, every half of the period, 5 ns in this case, the clock will flip itself. To simulate the clock signal, instead of putting it in the initialize statement, we will use an always statement. `timescale 1ns / 1ps ... reg clk; always #5 clk = ~clk; In the initialize block, we will initialize //clk// signal to 0 and hold //rst// high for 10ns to reset the clock divider. So, the Verilog Test Bench will look like this: `timescale 1ns / 1ps module tb; // Inputs reg clk; reg rst; // Outputs wire led; // Instantiate the Unit Under Test (UUT) clk_divider uut ( .clk(clk), .rst(rst), .led(led) ); always #5 clk = ~clk; initial begin // Initialize Inputs clk = 0; rst = 1; #10 rst = 0; // Wait 100 ns for global reset to finish #100; end endmodule The simulated waveform is shown in Fig. 5 below. You can see in the waveform that //clkdiv[0]// is half of the frequency of //clk//, and that //clkdiv[1]// is half of the frequency of //clkdiv[2]//. {{ :learn:programmable-logic:tutorials:use-flip-flops-to-build-a-clock-divider:dividersim.png?direct |Figure 5. Clock divider simulation waveform. Screenshot is from Xilinx ISim running on Microsoft Windows 7. Altered to enhance visual understanding.}} Now you can create a UCF file that maps clk to the global clock on board, rst to a push button, and led to an on-board LED. If your board has a 100 MHz clock, you can see that the LED blinks once every 1.45 seconds. ===== Challenges ===== Now that you've completed this project, try these modifications: - Can you add two switches to control how fast the LED blinks: Say, if switch[1:0] is 0, LED blink frequency is 0.745 Hz; if switch[1:0] is 1, LED blink frequency is 1.49 Hz; if switch[1:0] is 2, LED blink frequency is 2.98 Hz; if switch[1:0] is 3, LED blink frequency is 5.96 Hz. {{tag>learn programmable-logic project nexys-4 nexys-3 nexys-2 basys-2 flip-flops clock divider}}