COE 202 Introduction to Verilog Computer Engineering Department College of Computer Sciences and Engineering King Fahd University of Petroleum and Minerals
Outline Procedural Assignment (review) D Latch D Flip Flop Structural Modeling of a Sequential Circuit FSM Modeling Parallel Load Register Shift Register Up-Down Counter
Procedural Assignment (review) Assignments inside an always block are called procedural assignments Can only be used within an always block Two types: blocking and nonblocking: [variable-name] = [expression] ; // blocking assignment [variable-name] <= [expression] ; // nonblocking assignment Blocking – expression is evaluated and then assigned to the variable immediately before execution of the next statement. Nonblocking – evaluated expression is assigned at the end of the always block. The basic rule of thumb is: Use blocking assignments for a combinational circuit. Use nonblocking assignments for a sequential circuit
D Latch module dlatch (output q, input data, enable); assign q = enable ? data: q; endmodule module dlatch2 (output reg q, input data, enable); always @(enable, data) if (enable) q <= data; //Notice the use of non-blocking endmodule // assignment—This is the case with // sequential circuits
D Flip Flop – Synchronous Set/Reset module dff (output reg q, output q_bar, input data, set, reset, clk); assign q_bar = ~q; // “assign” statement can’t be inside // an “always” block always @(posedge clk) // Synchronous set/reset if (reset) q <= 0; // Again non-blocking assignments else if (set) q <=1; else q <= data; endmodule
D Flip Flop – Asynchronous Set/Reset module dff2 (output reg q, output q_bar, input data, set, reset, clk); assign q_bar = !q; always @(posedge clk, posedge set, posedge reset) if (reset == 1'b1) q <= 0; // Asynchronous set/reset else if (set == 1'b1) q <=1; else q <= data; endmodule
Structural Modeling of a Sequential Circuit module SeqStruct(output Y, input X, Reset, CLK); dff2 F0 (B, Bb, DB, 1'b0, Reset, CLK); dff2 F1 (A, Ab, DA, 1'b0, Reset, CLK); and (DB, Ab, X); and (w1, A, X); and (w2, B, X); or (DA, w1, w2); or (w3, A, B); not (w4, X); and (Y, w3, w4); endmodule We do this if we already have the design (i.e. schematic)
Behavioral Modeling of a Sequential Circuit module SeqStruct (output wire Y, input X, Reset, CLK); reg A, B ; wire DA = (A & X ) | (B & X) ; //next state logic wire DB = ~A & X ; assign Y = (A | B) &~X ; // output // behavioral implementation of the FFs // with asynchronous active-low reset always @(posedge clk, negedge Reset) if (!Reset) {A,B} <= 2’b00 ; else {A,B} <= {DA,DB} ; endmodule We do this if we already have the design equations
Behavioral Modeling of FSMs FSM is a finite-state-machine (i.e., a sequential circuit) described by a state diagram Real power of Verilog is in modeling an FSM behaviorally No need for circuit implementation first! Synthesis tool produces the circuit implementation for us. Three basic parts of an FSM model: state register next state logic output logic Two main modeling styles: Explicit: one “always” block for the state register, and another for the next state and output logic Implicit: state register is implicit in the next state logic – separate output logic
Behavioral Modeling of FSMs Example: Moore Sequence Detector: Detection sequence is 110 IF 110 found on x Then Z gets ‘1’ Else z gets ‘0’ End x z clk 1 1 1 Reset /0 got1 /0 got11 /0 got110 /1 1
Implicit Modeling of FSMs: Moore module moore_110_detector (output wire z, input x, clk, rst); localparam reset = 2'b00, got1=2'b01, got11=2'b10, got110=2'b11; reg [1:0] state; assign z = (state== got110); //the Moore output – can't be inside the always // block below always @(posedge clk) //This is only for the state transition if (rst) state <= reset; else case (state) reset: if (x) state <= got1; else state <= reset; got1: if (x) state <= got11; else state <= reset; got11: if (x) state <= got11; else state <= got110; got110: if (x) state <= got1; else state <= reset; endcase endmodule
Behavioral Modeling of FSMs: Mealy Example: Mealy Sequence Detector: Detection sequence is 110 IF 110 found on x Then Z gets ‘1’ Else z gets ‘0’ End x z clk Reset got1 got11 0/0 1/0 0/1
Implicit Modeling of FSMs: Mealy module Mealy_110_detector (output wire z, input x, clk, rst ); localparam reset = 2'b00, got1=2'b01, got11=2'b10, got110=2'b11; reg [1:0] state; assign z = (state== got11) & ~x; // Note the Mealy output (i.e., func. of P.S. & input) always @(posedge clk) //This is only for the state transition if (rst) state <= reset; else case (state) reset: if (x) state <= got1; else state <= reset; got1: if (x) state <= got11; else state <= reset; got11: if (x) state <= got11; else state <= reset; default: state <= reset; //we added this since there is an unused state now endcase endmodule Reset got1 got11 0/0 1/0 0/1
FSM Modeling: Test benches To test an FSM (i.e. sequential circuit), the test bench must supply an input sequence that exercise all state transitions and output combinations module moore_110_detector_TB; //No ports for test benches reg clk, rst, x; // Inputs declarations – have to be reg type since we are going to // assign them inside a procedural block wire z; // output declaration – must be a wire since it is connected to the // output of the instantiated module moore_110_detector M1 (z, x, clk, rst); // instantiating the module under test initial begin // reset and clock sequence rst = 0; clk = 0; #10; rst = 1; forever #10 clk = ~ clk; end initial begin // Input sequence – apply inputs with negative edge of clock @(negedge clk) x = 0; @(negedge clk) x = 1; @(negedge clk) x = 1; @(negedge clk) x = 1; @(negedge clk) x = 1; @(negedge clk) x = 0; @(negedge clk) x = 0; end endmodule
Parallel Load Register module Par_load_reg4 #(parameter word_size=4) (output reg [word_size-1:0] Data_out, input [word_size-1:0] Data_in, input load, clock, reset); always @(posedge clock, posedge reset) //asynchronous reset if (reset) Data_out <= 0; else if (load) Data_out <= Data_in; endmodule
Shift Register (No shift control) module Shift_reg4 #(parameter word_size=4) (output Data_out, input Data_in, clock, reset); // Serial-in, serial-out reg [word_size-1:0] Q; assign Data_out = Q[0]; always @(posedge clock, negedge reset) //asynchronous reset if (!reset) Q <= 0; else Q <= {Data_in, Q [word_size-1:1]} ; endmodule
Shift Register (with shift control) module Shift_reg4 #(parameter word_size=4) //Serial-in, Parallel-out (output reg [word_size-1:0] Data_out, input Data_in, shift, clock, reset); always @(posedge clock, negedge reset) //asynchronous reset if (!reset) Data_out <= 0; else if (shift) Data_out <= {Data_in, Data_out[word_size -1:1]}; //Shifts to endmodule // the right
MultiFunction Register module MFRegister #(parameter n=4) (output reg [n-1:0] Q, input [n-1:0] Din, input s1, s0, clk, reset, SiL, SiR); always @(posedge clk) begin if (reset) Q <= 0; // synchronous reset else case ({s1,s0}) 2'b00: Q <= Q; // no change 2'b01: Q <= Din; // parallel load – Read Din into register 2'b10: Q <= {Q [n-2:0], SiR}; // shift left, SiR is shifted in from the right 2'b11: Q <= {SiL, Q [n-1:1]}; // shift right, SiL is shifted in from the left endcase end endmodule
Up-Down Counter module Up_Down_Counter2 (output reg [2:0] count, input load, count_up, counter_on, clock, reset, input [2:0] Data_in); always @(negedge clock, posedge reset) // counter is –ve edge triggered if (reset) count <= 0; else if (counter_on) // If counter_on is 0, counter does nothing if (load) count <= Data_in; else if (count_up) count <= count+1; else count <= count-1; endmodule
Up-Down Counter: Testbench module TB_Counter ; reg [2:0] Data_in ; reg load, count_up, counter_on, clock, reset ; wire [2:0] Q ; //output Up_Down_Counter2 (Q, load, count_up, counter_on, clock, reset, Data_in); initial begin // The reset and clock sequence reset = 1; clk = 0; #10; reset = 0; forever #10 clk = ~ clk; end initial begin counter_on=0; load=0; count_up=0; Data_in=5; // initialize inputs @(posedge clk) counter_on=1; load=1; // load with 5 @(posedge clk) count_up=1; load=0; // count up to 6 @(posedge clk); // count up to 7 @(posedge clk) count_up=0; // count down to 6 @(posedge clk); // count down to 5 end endmodule
Modulo-n Counter module Modulo_n_Counter # (Parameter M=4, N=7) (output reg [M-1:0] count, input count_en, clock, reset); always @(posedge clock, posedge reset) if (reset) count <= 0; //If count_en is 0, counter does nothing else if (count_en) if (count == N-1) count <= 0; else count<=count+1; endmodule
Backup Slides
Explicit Modeling of FSMs: Moore module moore_110_detector (output reg z, input x, clk, rst); localparam reset = 2'b00, got1=2'b01, got11=2'b10, got110=2'b11; reg [1:0] state, next_state; always @(posedge clk) // synch reset if (rst) state <= reset; else state <= next_state; // the state transition always @(state, x) begin // comb. logic z = 0; // Default value of z – VERY IMPORTANT case (state) // Note the use of blocking assignments with // combinational logic reset: if (x) next_state=got1; else next_state=reset; got1: if (x) next_state=got11; else next_state=reset; got11: if (x) next_state=got11; else next_state=got110; got110: begin z=1; if (x) next_state=got1; else next_state=reset; end endcase // When we have more than one statement inside a end // “case” branch, we use begin..end endmodule
Explicit Modeling of FSMs: Mealy module Mealy_110_detector (output reg z, input x, clk, rst ); localparam reset = 2'b00, got1=2'b01, got11=2'b10; reg [1:0] state, next_state; always @(posedge clk) // synch reset if (rst) state <= reset; else state <= next_state; // the state transition always @(state, x) begin // comb. logic z = 0; // Default value of z – VERY IMPORTANT case (state) // Note the use of blocking assignments with // combinational logic reset: if (x) next_state=got1; else next_state=reset; got1: if (x) next_state=got11; else next_state=reset; got11: if (x) next_state=got11; else begin z = 1; next_state=reset; end // begin ..end for the if branch default: state <= reset; //we added this since there is an unused state now endcase end endmodule Reset got1 got11 0/0 1/0 0/1
A clock frequency divider Whenever we divide by powers of 2 (using counters), the output is symmetrical (i.e., the high and low durations are equal) Division by other numbers will give non-symmetrical output module CLK_Divider # (Parameter M=4, N=7) // N is the division ratio (output wire clk_out, input clk_in, reset); reg [M-1:0] count ; //2M must be larger than N assign clk_out = (count == N - 1) ; always @(posedge clk_in, posedge reset) if (reset) count <= 0; else if (clk_out) count <= 0; else count <= count+1; endmodule
Explicit Modeling of FSMs: Mealy module Mealy_110_detector (output wire z, input x, clk, rst ); // another way .. localparam reset = 2'b00, got1=2'b01, got11=2'b10; reg [1:0] state, next_state; assign z = (state==got11) & ~x; // Mealy O/Ps always @(posedge clk) // synch reset if (rst) state <= reset; else state <= next_state; // the state transition always @(state, x) begin // comb. logic z = 0; // Default value of z – VERY IMPORTANT case (state) // Note the use of blocking assignments with // combinational logic reset: if (x) next_state=got1; else next_state=reset; got1: if (x) next_state=got11; else next_state=reset; got11: if (x) next_state=got11; else begin next_state=reset; default: state <= reset; //we added this since there is an unused state now endcase end endmodule Reset got1 got11 0/0 1/0 0/1