1

I want to design a variable shift register to shift to the right as follows:

module sr(N,int,out);

  input [2:0] N;
  input [7:0] in;
  output [7:0] out;

  assign out={N'b0,input[7,N]}

endmodule

But unfortunately, Verilog doesn't allow this kind of writing. N should be constant. Any idea on how to get shift iterations from input?

5
  • I think it's not allowed because it causes an exponential explosion in required amount of logic as the parameters get larger. Do you need this for the general case, or just for that particular small example? For a 3 bit N it would be easy to just write a switch statement. Commented Aug 13, 2012 at 14:30
  • @Tim - just because the logic is big, doesn't mean it shouldn't be allowed though :) Commented Aug 13, 2012 at 14:49
  • 3
    If I understand correctly, you want a barrel shifter: stackoverflow.com/questions/7543592/verilog-barrel-shifter Commented Aug 13, 2012 at 14:50
  • Your original code has a syntax error (input[7,0]) as well as a bunch of mismatched names. See my answer for corrections. Commented Aug 13, 2012 at 14:53
  • yea this is a dummy code, just to show the concept. Commented Aug 13, 2012 at 17:48

2 Answers 2

6

Verilog has a right shift operator so you can simply write:

assign out = in >> N;

The extra bits are automatically filled with zeros.

Sign up to request clarification or add additional context in comments.

1 Comment

yes this is correct but the execution time of this type of shift is double of : assign out={[N'b0,in[7:N]}. but here N should be constant
3

If the sizes of in and out are really fixed at 8 bits, here is one simple way to do it:

module sr(N, in, out);

  input  [2:0] N;
  input  [7:0] in;
  output [7:0] out;

  assign out = (N == 7) ? {7'b0, in[7:7]} : 
               (N == 6) ? {6'b0, in[7:6]} : 
               (N == 5) ? {5'b0, in[7:5]} : 
               (N == 4) ? {4'b0, in[7:4]} : 
               (N == 3) ? {3'b0, in[7:3]} : 
               (N == 2) ? {2'b0, in[7:2]} : 
               (N == 1) ? {1'b0, in[7:1]} : 
                                 in[7:0];

endmodule

This could also be coded using a case statement inside an always block, like this:

  reg [7:0] out_reg;
  assign out = out_reg;

  always @(N or in) begin
    case (N)
      7 : out_reg <= {7'b0, in[7:7]};
      6 : out_reg <= {6'b0, in[7:6]};
      5 : out_reg <= {5'b0, in[7:5]};
      4 : out_reg <= {4'b0, in[7:4]};
      3 : out_reg <= {3'b0, in[7:3]};
      2 : out_reg <= {2'b0, in[7:2]};
      1 : out_reg <= {1'b0, in[7:1]};
      0 : out_reg <=        in[7:0];
    endcase
  end

If you don't want to write out all the values you can use a for loop. I'm not an expert on how the synthesis tools handle this but this (or something similar) should synthesize okay.

  always @(N or in) begin
    for (i = 0; i < 8; i = i + 1) begin
      if (i+N < 8) begin
        out_reg[i] <= in[i+N];
      end else begin
        out_reg[i] <= 1'b0;
      end
    end
  end

One advantage of coding it using a loop is it is less prone to cut-n-paste typos.

More importantly, if you want to make the module support generic bit-widths of the inputs and outputs, you can do so using a parameter on the module and a similar loop for the assignments.

1 Comment

tanx dwikle, I like the first code. I have at least 9 inputs, and 9 Ns. it means a crowded code. but seems there is no other choice

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.