一、题目说明——HDLbits_Mux256to1v
Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel=0 should select bits in[3:0], sel=1 selects bits in[7:4], sel=2 selects bits in[11:8], etc.
二、思路分析和实现
- With this many options, a case statement isn't so useful.
- Vector indices can be variable, as long as the synthesizer can figure out that the width of the bits being selected is constant. It's not always good at this. An error saying "... is not a constant" means it couldn't prove that the select width is constant. In particular, in[ sel*4+3 : sel*4 ] does not work.
- Bit slicing ("Indexed vector part select", since Verilog-2001) has an even more compact syntax.
编写时发现,不能使用in[sel*4+3:sel*4]这样的形式,会发生报错:sel不是一个常数。因此需要选择其他的方式描述。
思路一 Case 在always块中使用case,但是这在3选1、4选1等情况少的时候比较直观和方便,对于256选1,我们需要写完256种情况,这太多太复杂了。例如:
module multiplexer_256_1 (
input [1023:0] in, // 输入向量
input [7:0] sel, // 选择信号
output reg [3:0] out // 输出信号
);
always @(*)begin
case (sel)
8'h00: out = in[3:0];
8'h01: out = in[7:4];
8'h02: out = in[11:8];
// ... 其他选择分支 ...
8'hFF: out = in[1023:1020];
default: out = 4'b0000;
endcase
end
endmodule
思路二 Generate 使用循环生成块来完成,在生成块内i被视为常数,可以在切片中描述。
(在HDLbits中编译通过但仿真不通过,存在警告)
# ** Warning: Design size of 16384 statements exceeds ModelSim-Intel FPGA Starter Edition recommended capacity. # Expect performance to be adversely affected.
module multiplexer_256_1 (
input [1023:0] in, // 输入向量
input [7:0] sel, // 选择信号
output [3:0] out // 输出信号
);
wire [3:0] out_wire [255:0];
assign out = out_wire[255];
genvar i;
generate for(i=0;i<256;i=i+1)begin:for_loop
if(!i)
assign out_wire[i] = (sel== 0) ? in[3:0] : 4'b0;
else
assign out_wire[i] = (sel-i== 0) ? in[3+i*4:i*4] : out_wire[i-1];
end
endgenerate
endmodule
思路三 移位 使用根据sel的每一位的情况对[1023 : 0] in进行不同的移位。编译仿真成功。
module multiplexer_256_1 (
input [1023:0] in, // 输入向量
input [7:0] sel, // 选择信号
output [3:0] out // 输出信号
);
integer i;
reg [1023:0] in_reg ;
assign out = in_reg[3:0];
always@(*)begin
in_reg = in;
for(i=7;i>=0;i=i-1)
if(sel[i])
in_reg = in_reg >>(4*2**i);
end
endmodule
思路四 Select one bit or Indexed vector part select
module multiplexer_256_1 (
input [1023:0] in,
input [7:0] sel,
output [3:0] out
);
// We can't part-select multiple bits without an error, but we can select one bit at a time,
// four times, then concatenate them together.
assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};
// Alternatively, "indexed vector part select" works better, but has an unfamiliar syntax:
// assign out = in[sel*4 +: 4]; // Select starting at index "sel*4", then select a total width of 4 bits with increasing (+:) index number.
// assign out = in[sel*4+3 -: 4]; // Select starting at index "sel*4+3", then select a total width of 4 bits with decreasing (-:) index number.
// Note: The width (4 in this case) must be constant.
endmodule