Search code examples
verilogdigital-logicshift-register

Synthesizable Verilog modular shift register


I'm doing a LOTTT of pipelining with varying width signals and wanted a SYNTHESIZEABLE module wherein i could pass 2 parameters : 1) number of pipes (L) and 2) width of signal (W).

That way i just have to instantiate the module and pass 2 values which is so much simple and robust than typing loads and loads of signal propagation via dummy registers...prone to errors and et all.

I have HALF written the verilog code , kindly request you to correct me if i am wrong.

I AM FACING COMPILE ERROR ... SEE COMMENTS

*****************************************************************
PARTIAL VERILOG CODE FOR SERIAL IN SERIAL OUT SHIFT REGISTER WITH
1) Varying number of shifts / stages  : L 
2) Varying number of signal / register width : W
*****************************************************************

module SISO (clk, rst, Serial_in, Serial_out);  // sIn -> [0|1|2|3|...|L-1] -> sOut
parameter L = 60; //   Number of stages
parameter W = 60; //   Width of Serial_in / Serial_out 

input  clk,rst;
input  reg Serial_in; 
output reg Serial_out;


// reg [L-1:0][W-1:0] R; 
reg [L-1:0] R;           // Declare a register which is L bit long

always @(posedge clk or posedge rst) 
begin
  if (rst)                  // Reset = active high  
//**********************
     begin
        R[0] <= 'b0;            // Exceptional case : feeding input to pipe 
        Serial_out <= 'b0;      // Exceptional case : vomiting output from pipe 

     genvar j;
     for(j = 1; j<= L; j=j+1)   // Ensuring ALL registers are reset when rst = 1
     begin : rst_regs           // Block name = reset_the_registers
        R[L] <= 'b0;            // Verilog automatically assumes destination width @ just using  'b0
     end
     end
  else
//**********************
    begin
        generate
        genvar i;
        for(i = 1; i< L; i=i+1) 
            begin : declare_reg
                R[0] <= Serial_in;    // <----  COMPILE ERROR POINTED HERE 
                R[L] <= R[L-1];       
                Serial_out <= R[L-1];
            end
        endgenerate;
    end
//**********************
 endmodule
//**********************

Solution

  • Why so complicated? The following code would be much simpler and easier to understand:

    module SISO #(
        parameter L = 60, // Number of stages (1 = this is a simple FF)
        parameter W = 60  // Width of Serial_in / Serial_out
    ) (
        input clk, rst,
        input [W-1:0] Serial_in,
        output [W-1:0] Serial_out
    );
        reg [L*W-1:0] shreg;
    
        always @(posedge clk) begin
            if (rst)
                shreg <= 0;
            else
                shreg <= {shreg, Serial_in};
        end
    
        assign Serial_out = shreg[L*W-1:(L-1)*W];
    endmodule
    

    However, looking at your code there are the following problems:

    1. You declare Serial_in as input reg. This is not possible, an input cannot be a reg.

    2. You are using generate..endgenerate within an always block. A generate block is a module item and cannot be used in an always block. Simply remove the generate and endgenerate statements and declare i as integer.

    3. Obviously Serial_in and Serial_out must be declared as vectors of size [W-1:0].

    4. You are using R as a memory. Declare it as such: reg [W-1:0] R [0:L-1].

    5. You are not using i in you for loop. Obviously you meant to chain all the elements of R together, but you are just accessing the 0th, (L-1)th and Lth element. (Obviously the Lth element is nonexisting, this array would be going from 0 to L-1.

    I'm now stopping writing this list because, I'm sorry, I think there really is not much to gain by improving the code you have posted..