ꭝꭝ The Verilog® Hardware Description Language, Donald E. Thomas (Author), Philip R. Moorby (Author) ISBN:9781402070891 Amazon Link
Controller FSM
Datapath
Datapath operations can be encoded within the same procedural code as the state machine description or can be built separately.
First consider partitioning.
example find borg|car|cat|bat|bot|bet|bit and output done flag where done is a registered output
done flag logic cannot be coded directly based on CS and with the final states
registered outputs in general must coded once per transistion, though the existance of one common default may save some lines of code
always @ (posedge clk) begin CS<=failed; //defaults found<=0; done<=0; //defaults case (CS) ... recieved_a: if (input =='r') begin CS<=recieved_r_for_car; done<=1; found<=1; end else if (input =='t') begin CS<=recieved_t; done<=1; found<=1; end else begin CS<=failed; //covered by default done<=1; found<=0; end ...
output logic coded with use of next state NS
CS<=failed; found<=0; done<=0; //defaults case (NS) recieved_t:done<=1;found<=1; recieved_r_for_car:done<=1;found<=1; recieved_g:done<=1;found<=1; failed:done<=1;found<=0; default:done<=0; ...
case(CS) S0:begin dx <= x1-x0; busy<= 1; end S1:dx <= y1-y0; S2:dxSq <= dx*dx; S3:dySq <= dy*dy; S4:begin dsq <= dxSq+dySq; busy<= 0; end endcase
At times we’ll want to include an extra register to store information that we don’t want to code as part of our primary state register.
These extended state registers are not necessarily represented by the number of drawn states state transition diagram or the primary coded state register, but formally they ARE part of the state of the system
note the explicit state register and the additional extended state registers
Some Options:
Unconditional Delay Using Extra States
Unconditional Delay Using Extended State Register Variable : Counter
Minimal Pause: Delay + Conditional Exit Using An Extra State (unconditional delay +conditional exit)
Minimum Wait: Delay + Conditional Exit Using Extended State Register Variable Counter
Realizations of i,j registers and support hardware
Wrong Code State D
SA: i<=0; ... SD: i <= i+1; if (i<10) CS<=SA; else CS<=SE; ….
Correct Code State D
SD: next_i = i+1; if (next_i<10) CS<=SA; else CS<=SE; i <= next_i; ….
Wrong Code State D
SA: i<=0; ... SD: i <= i+1; if (i<10) CS<=SA; else CS<=SE; ….
Tweaked / “Hacked”
SA: i<=0; ... SD: i <= i+1; if (i<9) CS<=SA; else CS<=SE; ….
When looking for a change on an signal, avoid a careless temptation to “detect” edges using edge specifiers if it is not warranted to create a new clock domain. Ex:
always @ (posedge e) e_counter <= e_counter + 1;
Consider saving a previous version of the signal in a register, and using both present and previous input values to detect a transition:
always @ (posedge clk) begin if (~e_prev & e) e_counter <= e_counter + 1; e_prev<=e; end
which is the same as
always @ (posedge clk)begin e_prev<=e; if (~e_prev & e) e_counter <= e_counter + 1; end
To alter the behavior, a slave state machine can instead look for a change in the signal in two consecutive clock cycles
Saving the previous input value:
always @ (posedge clk) go_prev<=go;
using a fresh high as a condition
(go==1 && go_prev==0)
switch(current_state){ case A: … case B: … case C: … case D: … }
if (exception){ do this }else{ switch(current_state){ case A: … case B: case C: case D: }
Module Header
module FSM_opt( output reg [7:0] f, input clk, input wire [7:0] i, input wire [7:0] j, input wire [7:0] k, input rst ); reg [7:0] CS; reg [7:0] i_int,j_int,k_int; localparam S_0 = 8'b00000000; localparam S_1 = 8'b00000001; localparam S_2 = 8'b00000010;
Module Body
always @ (posedge clk) begin if (rst) begin CS<=S_0; f<=0; end else begin case(CS) S_0: begin i_int<=i; j_int<=j; k_int<=k; CS<=S_1; end S_1: begin CS<=S_2; end S_2: begin m=i_int*j_int; f<=m*k_int; CS<=S_0; end endcase end end endmodule
RTL suggested from Code
Only datapath connections shown, control and status signals are ommitted
always @ (posedge clk) begin if (rst) begin CS<=S_0; f<=0; end else begin case(CS) S_0: begin i_int<=i; j_int<=j; k_int<=k; CS<=S_1; end S_1: begin m<=i_int*j_int; //**to here** CS<=S_2; end S_2: begin //m=i_int*j_int; //**move from here** f<=m\*k_int; CS<=S_0; end endcase end end endmodule
Rescheduling this multiply allows for faster clock rates ( assuming two clock cycles were required at the system level). Some synthesizers may do similar types of rescheduling for you.
Reference Computation Module for discussion
Head
module FSM_opt( output reg [7:0] f, output reg [7:0] g, input clk, input wire [7:0] i, input wire [7:0] j, input wire [7:0] k, input rst ); reg [7:0] CS; reg [7:0] i_int,j_int,k_int; localparam S_0 = 8'b00000000; localparam S_1 = 8'b00000001; localparam S_2 = 8'b00000010;
Body
always @ (posedge clk) begin if (rst) begin CS<=S_0; f<=0; h<=0; end else begin case(CS) S_0: begin i_int<=i; j_int<=j; k_int<=k; CS<=S_1; end S_1: begin CS<=S_2; end S_2: begin f<=i_int*j_int; h<=j_int*k_int; CS<=S_0; end endcase end end endmodule
always @ (posedge clk) begin if (rst) begin f<=0; g<=0; CS<=S_0; end else begin case(CS) S_0: begin i_int<=i; j_int<=j; k_int<=k; CS<=S_1; end S_1: begin CS<=S_2; end S_2: begin f<=i_int*j_int; //** g<=j_int*k_int; CS<=S_0; end endcase end end endmodule
Explicitly coding the rescheduling so that only one multiply is performed per cycle is simple and seen in the next code. However, this doesn’t ensure resource sharing as shown in the figure with one a single multiplier.
Alt. Module Body
always @ (posedge clk) begin if (rst) begin f<=0; g<=0; CS<=S_0; end else begin case(CS) S_0: begin i_int<=i; j_int<=j; k_int<=k; CS<=S_1; end S_1: begin f_int<=i_int*j_int; //**moved to here**// CS<=S_2; end S_2: begin f<=f_int; //*timed output load*// g<=k_int*j_int; CS<=S_0; end endcase end end endmodule
always @ (posedge clk) begin:named reg [15:0] mult_out; mult_out = 16'bx; if (rst) begin f<=0; g<=0; CS<=S_0; end else begin case(CS) S_0: begin i_int<=i; j_int<=j; k_int<=k; CS<=S_1; end S_1: begin mult_out=i_int*j_intl; //** f_int<=mult_out; //** CS<=S_2; end S_2: begin f<=f_int; mult_out=k_int*j_int; //** g<=mult_out; //** CS<=S_0; end endcase end end endmodule
Version 1
… always @ (posedge clk) … case (CS) S_0:begin q<=r+s; CS<=S_1; end S_1:begin CS<=S_2; end S_2:begin qout<=q+5; CS<=S_0; end …
Version 2
… always @ (posedge clk) … case (CS) S_0:begin q<=r+s; CS<=S_1; end S_1:begin q<=q+5; CS<=S_2; end S_2:begin qout<=q; CS<=S_0; end …
Code Provided to the Synthesizer
input [7:0] i,j,k; output [7:0] f,h; reg [7:0] f,g,h,q,r,s; always @ (posedge clk) … case (CS) S_0:begin[ f<=i+j; g<=j*23; CS<=S_1; end S_1:begin[ h<=f+k; CS<=S_2; end S_2:begin[ f<=f*g; q<=r*s; CS<=S_0; end …
Movement of q=r*s using a temporary variable:
S_0:begin[ f<=i+j; g<=j*23; CS<=S_1; end S_1:begin[ h<=f+k; q_int<=r*s; CS<=S_2; end S_2:begin[ f<=f*g; q<=q_int; CS<=S_0; end
Movement of f*g:
S_0:begin[ f<=i+j;g<=j*23; CS<=S_1; end S_1:begin[ h<=f+k;g<=f*g; CS<=S_2; end S_2:begin[ f<=g; q<=r*s; CS<=S_0; end
Log File Example
Synthesizing Unit <fsm_1>. Related source file is "/state_machines_1.vhd". Found finite state machine <FSM_0> for signal <state>. ------------------------------------------------------ | States | 4 | | Transitions | 5 | | Inputs | 1 | | Outputs | 4 | | Clock | clk (rising_edge) | | Reset | reset (positive) | | Reset type | asynchronous | | Reset State | s1 | | Power Up State | s1 | | Encoding | automatic | | Implementation | LUT | ------------------------------------------------------ Found 1-bit register for signal <outp>. Summary: inferred 1 Finite State Machine(s). inferred 1 D-type flip-flop(s). Unit <fsm_1> synthesized. ========================================================
HDL Synthesis Report Macro Statistics # Registers : 1 1-bit register : 1 ======================================================== ======================================================== * Advanced HDL Synthesis * ======================================================== Advanced Registered AddSub inference ... Analyzing FSM <FSM_0> for best encoding. Optimizing FSM <state/FSM_0> on signal <state[1:2]> with gray encoding. ------------------- State | Encoding ------------------- s1 | 00 s2 | 01 s3 | 11 s4 | 10 ------------------- ======================================================= HDL Synthesis Report Macro Statistics # FSMs : 1 =======================================================
casex select // synthesis full_case 4'b1xxx: res = data1; 4'bx1xx: res = data2; 4'bxx1x: res = data3; 4'bxxx1: res = data4;
// synopsys translate_off default: \$display(“He’s dead, Jim.”) ; // synopsys translate_on
http://www.xilinx.com/support/documentation/sw_manuals/xilinx11/pp_db_xst_hdl_synthesis_options.htm
Example state machine code if time allows
Example FFT Data Flow HW solution depicting extended state registers and state repetition