Search code examples
verilogsystem-verilogfpgaregister-transfer-level

Delay a 32-bit signal with N clock cycle in verilog


I am trying to delay a 32-bit signal using shift register. My logic is a single flip flop delay a signal by 1 clk so I use shift register as it is combination of flip flop can someone guide me what is wrong with this code.

module delay_n_cycles (
  input wire [31:0] data_in,
  input wire clk,
  output reg [31:0] data_out,
  parameter N = 5
);

reg [31:0] shift_reg;

always @(posedge clk) begin
  shift_reg <= {shift_reg[30:0], data_in};
  if (N == 0) begin
    data_out <= shift_reg[31];
 end else begin
    data_out <= shift_reg[N-1];
  end
end

endmodule

Solution

  • First of all, your code is syntactically wrong. parameter cannot be declared in a way you provided.

    Your shift register is only 32 bit wide. Usually, to delay multi-bit data this way, you need to keep N copies of data in the register, shift them at one end and read at the other. I guess the following should help:

    module delay_n_cycles #(parameter N = 5)(
      input wire [31:0] data_in,
      input wire clk,
      output reg [31:0] data_out
    );
    
      reg [N-1:0][31:0] shift_reg;
    
    always @(posedge clk) begin
      shift_reg <= (shift_reg << 32) | data_in;
      data_out <= shift_reg[N-1];
    end
    endmodule
    

    This code will work with system verilog because it used packed multi-dimensional arrays.

    You need to shift the reg by 32 (width of the data) in packed version.

    Here is an example of a testbench:

    module tb();
      bit clk;
      int clkCount;
      initial 
        forever begin 
          #5 clk = ~clk;
          clkCount++;
        end
      
      logic [31:0] data_in, data_out;
      
      initial begin
        $monitor("%0t (%0d) [%h]: %0d --> %0d", $time, clkCount, ds.shift_reg[4], data_in, ds.data_out);
        
        for(int i = 0; i < 20; i++) begin
          #10 data_in = i;
        end
        $finish;
      end
      
      delay_n_cycles ds(data_in, clk, data_out);
    endmodule