Lecture 3 Behavioral Modeling Sequential Circuits Registers Counters Finite State Machines
Behavioral Modeling Behavioral Modeling Behavioral descriptions use the keyword always, followed by optional event control expression and a list of procedural assignment statements The event control expression specifies when the statements will execute The target output of a procedural assignment statement must of the reg type // Behavioral description of two-to-one multiplexer // Verilog 2001 module mux_2x1_beh ( output reg m_out, input A, B, select ); always @(A, B, select) if(select) m_out = A; else m_out = B; module // Behavioral description of two-to-one multiplexer // Verilog 2001 module mux_2x1_beh ( output reg m_out, input A, B, select ); always @(*) // or @* case(select) 1 b1: m_out = A; 1 b0: m_out = B; case module
Sequential Circuit Sequential Circuits A circuit whose state is specified by a time sequence of inputs, outputs and internal states The storage elements are circuits capable of storing binary information The binary information stored in these devices at any given time determine the state of the sequential circuit The sequential circuit receives binary information from the inputs that, together with the present state of the storage elements, determines the outputs
Sequential Circuits Two main types of Sequential Circuit Asynchronous, Synchronous Asynchronous Behavior (outputs/state) deps upon the input signals at any instant of time and the order in which the inputs change The storage elements commonly used are time-delay devices» The storage capability varies with logic gate propagation delay Varies with Process, Voltage and Temperature (PVT) May be regarded as a combinational circuit with feedback
Sequential Circuits Non-Storage Asynchronous Examples One Shot (Not sequential per definition as no FB) Ring Oscillator Must have odd number of stages Used as: clock source before main clock stable measure of PVT via frequency Voltage controlled Oscillator (VCO)
Sequential Circuits Non-Storage Asynchronous Examples Mercury Delay Lines Early computers required delay lines that had to be timed such that the pulses would arrive at the receiver just as the computer was ready to read it. Used acoustic pulses in the mercury to provide delay
Synchronous Sequential Circuits Employs signals that affect the storage elements at discrete instants of time Synchronization is achieved by using a clock signal Time stable periodic train of pulses Distributed throughout the device such that storage element are affect only with the arrival of each pulse Modern SoC may have several clock domains, i.e. areas of logic clocked by different clock speeds Timing is easily broken down into indepent discrete steps, each of which can be considered separately
Storage Elements: Flip Flops Direct Inputs Asynchronous set and/or reset inputs that force flip flop to a particular state indepently of the clock. Used to bring storage elements to know state upon power up or put system in an initial state May reset part several times during testing Asynchronously assert reset but de-assert synchronously Want all devices to come out of reset at the same time If reset released at or near active clock edge, flip flop output could go metastable FPGA flip flops initialize to zero upon programming.
Verilog Register Coding // D Flip Flop Asynchronous Reset Example always @(posedge Clk or posedge R) begin if(r == 1 b1) Q <= 1 b0; else Q <= D; // Another D Flip Flop Asynchronous Reset Example always @(posedge Clk, negedge R) if(!reset ) Q <=!Rb? 1 b0 : Data; // D Flip Flop Synchronous Reset Example always @(posedge Clk) begin if(r) Q <= 1 b0; else Q <= D; R D b b // D Flip Flop Synchronous Reset Example always @(posedge Clk) begin if(rb) Q <= 1 b0; else Q <= D; Rb D
Synchronous versus Asynchronous Reset Advantages The biggest advantage to using asynchronous resets is that, as long as the vor library has asynchronously resettable flip-flops, the data path is guaranteed to be clean. Designs that are pushing the limit for data path timing, can not afford to have added gates and additional net delays in the data path due to logic inserted to handle synchronous resets. This argument does not hold if the vor library has flipflops with synchronous reset inputs and the designer can get Synopsys to actually use those pins. Using an asynchronous reset, the designer is guaranteed not to have the reset added to the data path.
Synchronous versus Asynchronous Reset Disadvantages The biggest problem with asynchronous resets is that they are asynchronous, both at the assertion and at the deassertion of the reset. The assertion is a non issue, the de-assertion is the issue. If the asynchronous reset is released at or near the active clock edge of a flip-flop, the output of the flipflop could go metastable and thus the reset state of the ASIC could be lost. Another problem that an asynchronous reset can have, deping on its source, is spurious resets due to noise or glitches on the board or system reset.
Reset Synchronizer Circuit
Transistor count: Without Reset: Total: 10 transistors Asynchronous Reset: Replace upper two inverters with two input NANDs Total: 14 transistors Synchronous Reset: Add NOR in front of D Total: 14 transistors
Blocking versus Non-Blocking Blocking = Executed sequentially in the order they are listed in the block of statements initial begin A = B + 1; // Executes first B = W; // Executes second C = Z W; // Executes third Non-blocking <= Executes concurrently by evaluating the set of expressions on the right hand side and then make the left hand side assignments @(posedge clk) begin if(reset) begin A <= 8 h00; B <= 8 haa; else begin A <= X && Y; B <= W;
Blocking versus Non-Blocking What about case statement? Use blocking assignments to model combinational logic within an always block always @(A or B or S) begin : mux case (S) 1'b0: y = A; 1'b1: y = B; default: y = 1'bx; case Optional name
Inferred Latches Omitting a clause in a control construct (case, if-else) can cause an inferred latch always @(w, x, y, z, sel) case (sel) 2'b00: out = w; 2'b01: out = x; 2'b10: out = y; 2'b10: out = z; // TYPO. This line not executed, 2 b11 case missing. case always @(w, x, y, sel) // Missing z case (sel) 2'b00: out = w; 2'b01: out = x; 2'b10: out = y; 2'b10: out = z; // This line will not execute when z changes case Correct coding // out always assigned always @(w, x, y, sel) begin out = 4 h0; case (sel) 2'b00: out = w; 2'b01: out = x; 2'b10: out = y; case // out always assigned always @(w, x, y, sel) begin case (sel) 2'b00: out = w; 2'b01: out = x; 2'b10: out = y; default: out = 4 h0; case
Registers A register is a group of Flip Flips (FFs), each one of which shares a common clock and is capable of storing one bit of information. An n-bit register consists of a group of n FFs capable of storing n bits of information. Registers may have combinational logic that performs specific data processing tasks The FFs hold the binary information and the comb. Logic determines how the information is transferred into the register A counter is a specific type of register that goes through a predetermined sequence of binary states.
Registers Four-bit register with parallel load: Output A[3:0] changes with I[3:0] on Posedge of Clock module figure_6p1( input Clock, Clear_b, input [3:0] I, output reg [3:0] A ); always @(posedge Clock, negedge Clear_b) if (!Clear_b) A <= 4 h0; else A <= I; module
Registers Shift Registers: A register capable of shifting the binary information held in each cell to its neighboring cell in a predetermined direction Consists of a chain of FFs in cascade, with the output of one FF connected to the input of the next FF All FFs receive a common clock, which activate the shift of data from one stage to the next Can also incorporate a shift enable to activate/deactivate
Registers module fig6p3a( input CLK, SI, output SO); module fig6p3b( input CLK, SI, output SO); Note: blocking assignment reg [3:0] A; always @(posedge CLK) A <= {SI, A[3:1]}; assign SO = A[0]; module or reg [3:0] A; always @(posedge CLK) begin A = A >> 1; A[3] = SI; assign SO = A[0]; module Synopsys for right side example
Synchronous Counters: Synchronous Counters A clock pulse is applied to the clock inputs of all counter FFs Binary Counter: LSB FF complemented every clock pulse FFs in any other position are complemented when all the bits in the lower significant positions are equal to 1. module bincntr( input clk, clearb, input [7:0] datain, output reg [7:0] cnt); always @(posedge clk, negedge clearb) if (clearb == 1 b0) cnt <= 8'h00; else cnt <= cnt + 1; module
Synchronous Counters Binary Counter with Parallel Load, sync clear module bincntr( input clk, clearb, cntena, load, input [7:0] datain, output reg [7:0] cnt); always @(posedge clk) if (!clearb) cnt <= 8'h00; else if (load) cnt <= datain; else if (cntena) cnt <= cnt + 1; else cnt <= cnt; module
Ring Counter: Other Counters A circular shift register with only one flop being set at a given time Useful when trying to meet timing No Decoding (comb. logic) required One FF for each value, thus get big quickly module ringcntr( input clk, clearb, cntena, output reg [7:0] cnt); always @(posedge clk) if (!clearb) cnt <= 8'h80; else if (cntena) cnt <= {cnt[0], cnt[7:1]}; else cnt <= cnt; module
Synchronous Counters Up-Down Binary Counter: module bincntr( input clk, clearb, cntena, updwn, output reg [7:0] cnt; always @(posedge clk) if (!clearb) cnt <= 8'h00; else if (cntena) if(updwn) cnt <= cnt + 1; else cnt <= cnt - 1; else cnt <= cnt; module module bincntr_tb(); reg clk = 0; reg cntena = 0; reg clearb = 1; reg updwn = 1; wire [7:0] cnt; bincntr DUT(.clk(clk),.clearb(clearb),.cntEna(cntEna),.upDwn(upDwn),.cnt(cnt)); always #10 clk = ~clk; initial begin @(posedge clk) clearb = 0; @(posedge clk) clearb = 1; @(posedge clk) cntena = 1; repeat(10) @(posedge clk); cntena = 0; repeat(2) @(posedge clk); cntena = 1; repeat(2) @(posedge clk); updwn = 0; repeat(6) @(posedge clk); $stop; module
Binary Counter: module bincntr( input clk, clearb, cntena, output reg [7:0] cnt); always @(posedge clk) if (!clearb) cnt <= 8'h00; else if (cntena) cnt <= cnt + 1; // else // cnt <= cnt; module Synchronous Counters module bincntr_tb(); reg clk = 0; reg cntena = 0; reg clearb = 1; wire [7:0] cnt; bincntr DUT(.clk(clk),.clearb(clearb),.cntEna(cntEna),.cnt(cnt)); always #10 clk = ~clk; initial begin @(posedge clk) clearb = 0; @(posedge clk) clearb = 1; @(posedge clk) cntena = 1; repeat(10) @(posedge clk); cntena = 0; repeat(4) @(posedge clk); module
Synchronous Counters BCD Counter: module bcdcntr( input clk, clearb, cntena, output reg[7:0] cnt); always @(posedge clk) if (!clearb) cnt <= 8'h00; else if (cntena) if(cnt == 4'd9) cnt <= 4'd0; else cnt <= cnt + 1; else cnt <= cnt; module
Other Counters
Other Counters Johnson Counter: A k-bit ring counter circulates a single bit through the FFs to provide k unique states The number of states can be doubled if the shift register is connected as a switch-tail ring counter A switch-tail counter is a circular shift register with the complemented output of the last FF connected to the input of the last FF A Johnson counter is a k-bit switch tail ring counter with 2k decoded gates to provide 2k timing signals (not shown in Figure 6.18)
Fininte State Machines Mealy and Moore Models Finite State Machines Differ only in the way the output(s) is/are generated Mealy: output(s) function of both present state and input(s) Output(s) must be valid (stable) immediately before the clock active edge Moore: output(s) function of present state only Output(s) synchronized with the clock A circuit may have both types of outputs
FSM coding styles Many ways are possible Two common ways are: Two always blocks One for sequential logic One for combinational logic One always block Two always block is easiest to implement and understand and will be discuss here.
Two always blocks Sequential always block // State Register always @(posedge clk or posedge reset) if (reset) state <= IDLE; else state <= next_state; Combinational always block // Next State Case always @(*) begin next_state = 2 b00; case (state) IDLE: begin if (!in1) next = IDLE; if (in1 & in2) next = S1; if (in1 &!in2 & in3) next = S2; S1:
FSM Output Generation Code the output logic as either a separate block of continuous assignments or within the combinational always block // Mealy Outputs assign y = ((state == S1) (state == S2) (state == S3)) &&!x; always @(*) begin case({current_state[1:0], x}) 3'b000: begin next_state = 2'b00; y_sd = 0; 3'b001: begin next_state = 2'b01; y_sd = 0; 3'b010: begin next_state = 2'b00; y_sd = 1; 3'b011: begin next_state = 2'b11; y_sd = 0; case // case (current_state[1:0], x) // always @ (*)
Two always blocks Source: http://www.sunburst-design.com/papers/cummingsicu2002_fsmfundamentals.pdf
State Assignment // Binary Encoding parameter definitions parameter [1:0] IDLE = 2 b00, S1 = 2 b01, S2 = 2 b10, S3 = 2 b11; // One Hot Encoding parameter definitions parameter [3:0] IDLE = 4 b0001, S1 = 4 b0010, S2 = 4 b0100, S3 = 4 b1000; // One Cold Encoding parameter definitions parameter [3:0] IDLE = 4 b1110, S1 = 4 b1101, S2 = 4 b1011, S3 = 4 b0111; // Gray Code Encoding parameter definitions parameter [1:0] IDLE = 2 b00, S1 = 2 b01, S2 = 2 b11, S3 = 2 b10; Binary encoding only requires as many FFs as are needed to uniquely encode the number of state. One hot requires a FF for each state in the design and only one FF is set a time. One hot recommed for FPGA designs as FFs are plentiful with FPGAs and the combinational logic required is typically smaller. One hot designs typically run faster
module fig5p15(input x, Clock, output reg y_out); reg [1:0] current_state = 2'b00, next_state = 2'b00; reg [2*7:0] StateName; always @(*) begin StateName = "--"; case(current_state) 2'b00: StateName = "S0"; 2'b01: StateName = "S1"; 2'b10: StateName = "S2"; 2'b11: StateName = "S3"; case always @(posedge Clock) current_state <= next_state; always @(*) begin StateName = "--"; case(current_state) 2'b00: StateName = "S0"; 2'b01: StateName = "S1"; 2'b10: StateName = "S2"; 2'b11: StateName = "S3"; case always @(*) begin case({current_state[1:0], x}) 3'b000: begin next_state = 2'b00; y_out = 0; 3'b001: begin next_state = 2'b01; y_out = 0; 3'b010: begin next_state = 2'b00; y_out = 1; 3'b011: begin next_state = 2'b11; y_out = 0; 3'b100: begin next_state = 2'b00; y_out = 1; 3'b101: begin next_state = 2'b10; y_out = 0; 3'b110: begin next_state = 2'b00; y_out = 1; 3'b111: begin next_state = 2'b10; y_out = 0; case module