如何使我的verilog移位器更通用?

如何使我的verilog移位器更通用?,verilog,Verilog,这里我有一个移位器,但现在它最多只能工作3位。我一直在寻找,但我找不到如何使它最多工作8位 module shifter(a,b,out); input [7:0] a, b; output [7:0] out; wire [7:0] out1, out2, out3; mux_8b_2to1 first(a[7:0], {a[3:0],a[7:4]}, b[2], out1); mux_8b_2to1 second(out1[7:0], {out1[5:0],out1[7:6]}, b[1]

这里我有一个移位器,但现在它最多只能工作3位。我一直在寻找,但我找不到如何使它最多工作8位

module shifter(a,b,out);
input [7:0] a, b;
output [7:0] out;
wire [7:0] out1, out2, out3;

mux_8b_2to1 first(a[7:0], {a[3:0],a[7:4]}, b[2], out1);
mux_8b_2to1 second(out1[7:0], {out1[5:0],out1[7:6]}, b[1], out2);
mux_8b_2to1 third(out2[7:0], {out2[6:0],out2[7]}, b[0], out);
endmodule
我使用了>>和>b; 其他的 out=a你拥有的是一个。使其更通用的两种方法是使其成为功能模型(仍然可以进行合成)或具有生成块的结构模型。这两种方法都遵循IEEE标准1364-2001(又称Verilog-2001)

桶式换档器的功能通用方法只需要一个降档器。通用函数是
out={in,in}>>(宽度移位)
,其中可以忽略剩余位。要保护双滚动(即shift>WIDTH),请在shift上使用mod操作符(
WIDTH-(shift%WIDTH)

桶形移位器的结构通用方法需要生成块。generate块中的for循环将在编译时分解,而不是像always块中的for循环那样在运行时分解。为了保持通用性,2对1多路复用器也有一个参数化的宽度。仅供参考,您也可以将generate块与功能代码一起使用,例如注释掉
mux_2to1
实例化,并取消注释其下方的assign语句。通过阅读§27了解有关生成块的更多信息。生成构造

module barrel_shifter_structeral #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
 ( input wire [WIDTH-1:0] in,
   input wire [ CTRL-1:0] shift,
  output wire [WIDTH-1:0] out );
wire [WIDTH-1:0] tmp [CTRL:0];
assign tmp[CTRL] = in;
assign out = tmp[0];
genvar i;
generate
  for (i = 0; i < CTRL; i = i + 1) begin : mux
    mux_2to1 #(.WIDTH(WIDTH)) g(
      .in0(tmp[i+1]),
      .in1({tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]}),
      .sel(shift[i]),
      .out(tmp[i]) );
    // assign tmp[i] = shift[i] ? {tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]} : tmp[i+1];
  end : mux
endgenerate
endmodule

module mux_2to1 #( parameter WIDTH=8 )
 ( input wire [WIDTH-1:0] in0, in1,
   input wire             sel,
  output wire [WIDTH-1:0] out );
assign out = sel ? in1 : in0;
endmodule
模块桶移动器结构(参数CTRL=3,参数宽度=CTRL**2)
(输入线[宽度-1:0]英寸,
输入线[CTRL-1:0]移位,
输出线[WIDTH-1:0]输出);
导线[WIDTH-1:0]tmp[CTRL:0];
分配tmp[CTRL]=in;
分配输出=tmp[0];
genvar i;
生成
对于(i=0;i
这两个示例在功能上是等效的,只要
CTRL
小于或等于log2的上限(
WIDTH
)。合成可能会产生不同的结果。generate方法将专门使用2对1的MUX,而纯函数方法将取决于优化器的质量

工作示例@

Synthesizing Unit <shifter>.
    Related source file is "shifter.v".
    Found 8-bit shifter logical right for signal <out$shift0002> created at line 30.
    Found 8-bit shifter logical left for signal <out$shift0003> created at line 32.
module barrel_shifter_functional #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
 ( input wire [WIDTH-1:0] in,
   input wire [ CTRL-1:0] shift,
  output wire [WIDTH-1:0] out );
assign out = {2{in}} >> (WIDTH-(shift%WIDTH));
endmodule
module barrel_shifter_structeral #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
 ( input wire [WIDTH-1:0] in,
   input wire [ CTRL-1:0] shift,
  output wire [WIDTH-1:0] out );
wire [WIDTH-1:0] tmp [CTRL:0];
assign tmp[CTRL] = in;
assign out = tmp[0];
genvar i;
generate
  for (i = 0; i < CTRL; i = i + 1) begin : mux
    mux_2to1 #(.WIDTH(WIDTH)) g(
      .in0(tmp[i+1]),
      .in1({tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]}),
      .sel(shift[i]),
      .out(tmp[i]) );
    // assign tmp[i] = shift[i] ? {tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]} : tmp[i+1];
  end : mux
endgenerate
endmodule

module mux_2to1 #( parameter WIDTH=8 )
 ( input wire [WIDTH-1:0] in0, in1,
   input wire             sel,
  output wire [WIDTH-1:0] out );
assign out = sel ? in1 : in0;
endmodule