题目: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.
错误答案:
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out = in[sel<<2+3:sel<<2];
endmodule
报错提示:
Error (10734): Verilog HDL error at top_module.v(6): sel is not a constant File: /home/h/work/hdlbits.6774772/top_module.v Line: 6
正确答案:(提供了三种方法)
module top_module (
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
总结:
1.方法归纳:
方法一:一次选择一位,使用拼接符
方法二、方法三:使用矢量索引语法(这个语法以前没学过)
2.矢量索引语法 - 格式:
(1)in[sel*4+:4],从sel*4开始往高位取4个bit。
冒号前是起始索引位置,+号代表方向是往高位索引,冒号后面代表索引n个位。
(2)in[sel*4+3-:4],从sel*4+3开始往低位取4个bit。
冒号前是起始索引位置,-号代表方向是往低位索引,冒号后面代表索引n个位。
注意:冒号前的位置代表的是起始位置,并不代表是高位。也就是说,这个语法,以冒号前的位置作为起始位置,往高位或者低位取4位,然后再把这四位从高到低,放进4位宽的信号里。
3.错误原因
根据编译结果的提示,in[4*sel+3:4*sel]有错,“sel不是常数”。而从题目给的提示来看,应该是因为sel不是常数,所以导致了选择的位宽不是常数。
也就是说,不仅in[4*sel+3:4*sel]不可以,in[4*sel:8]也不可以(编译试过了,会报错);所以冒号两侧都不能出现变量,否则就会报错sel is not constant。
这是因为编译器会认为位宽选择时,如果出现了变量,则无法确定位宽到底是多少。(我猜,进而编译器就无法进行寻址取值等操作。)
4.而官方提供的三种方法为什么含有变量,却可以通过编译呢?
第一种方法是使用拼接符,每次都取一位,把四位拼接起来,所以虽然in[4*sel+3]中存在变量,但也不影响,因为这个变量的位数是确定的,就是1位。
第二种方法和第三种方法又是使用了矢量检索的语法,在这种语法下,in[sel*4+:4]中虽然也出现了变量,但是冒号后的4决定了取多少个位,也就是说位宽的选择是确定了的。