你拥有的是一个桶式移位器 http://en.wikipedia.org/wiki/Barrel_shifter。使其更加通用的两种方法是使其成为功能模型(仍然可综合)或具有生成块的结构模型。两种方法均遵循 IEEE Std 1364-2001(又名 Verilog-2001)。
桶式变速杆的功能性通用方法只需要一个降速杆。一般功能是out = {in,in} >> (WIDTH-shift)
其中剩余位可以被忽略。为了保护双卷(即 Shift > WIDTH ),请在 Shift 上使用 mod 运算符(WIDTH-(shift%WIDTH)
).
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
桶形移位器的结构通用方法需要一个生成块。 generate 块中的 for 循环将在编译时解开,而不是像always 块中的 for 循环那样运行时。为了保持通用性,2 选 1 多路复用器也必须具有参数化宽度。 仅供参考,您也可以将生成块与功能代码一起使用,例如注释掉mux_2to1
实例化并取消注释下面的分配语句。通过阅读了解有关生成块的更多信息IEEE 标准 1800-2012 https://standards.ieee.org/findstds/standard/1800-2012.html§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
小于或等于 log2(WIDTH
)。综合可能会产生不同的结果。生成方法将专门使用 2 对 1 多路复用器,而纯函数方法将取决于优化器的质量。
工作示例@http://www.edaplayground.com/s/6/500 http://www.edaplayground.com/s/6/500