verilog中的“+”
“+:”、"-:"语法
看到这个语法的时候是在分析AXI lite 总线源码时碰见的,初次遇见是在奇偶校验模块(ram_parity)然后查阅了资料,做出如下解释。
1.用处
这两个应该算是运算符,运用在多位的变量中,如下:
slv_reg0[(byte_index8) +: 8] <= S_AXI_WDATA[(byte_index8) +: 8];
2.“+:”
变量[起始地址 +: 数据位宽] <–等价于–> 变量[(起始地址+数据位宽-1):起始地址]
data[0 +: 8] <–等价于–> data[7:0]
data[15 +: 2] <–等价于–> data[16:15]
3.“-:”
变量[结束地址 -: 数据位宽] <–等价于–> 变量[结束地址:(结束地址-数据位宽+1)]
data[7 -: 8] <–等价于–> data[7:0]
data[15 -: 2] <–等价于–> data[15:14]
一 主题: +:语法说明
语法背景等等先来一遍(算是前言吧)
MARK
参考Verilog-2001语法规范
Bit-selects extract a particular bit from a vector net, vector reg, integer variable, or time variable. The bit can be addressed using an expression. If the bit-select is out of the address bounds or the bit-select is x or z, then the value returned by the reference shall be x. The bit-select or part-select of a variable declared as real or realtime shall be considered illegal.
Several contiguous bits in a vector net, vector reg, integer variable, or time variable can be addressed and are known as part-selects. There are two types of part-selects, a constant part-select and an indexed part-select.
A constant part-select of a vector reg or net is given with the following syntax:
vect[msb_expr:lsb_expr] 例如: vect[31:0]
Both expressions shall be constant expressions. The first expression has to address a more significant bit than the second expression. If the part-select is out of the address bounds or the part-select is x or z, then the value returned by the reference shall be x.
An indexed part select of a vector net, vector reg, integer variable, or time variable is given with the following syntax:
reg [15:0] big_vect;
reg [0:15] little_vect;
big_vect[lsb_base_expr +: width_expr]
little_vect[msb_base_expr +: width_expr]
big_vect[msb_base_expr -: width_expr]
little_vect[lsb_base_expr -: width_expr]
The width_expr shall be a constant expression. It also shall not be affected by run-time parameter assignments. The lsb_base_expr and msb_base_expr can vary at run-time. The first two examples select bits starting at the base and ascending the bit range. The number of bits selected is equal to the width expression. The second two examples select bits starting at the base and descending the bit range. Part-selects that address a range of bits that are completely out of the address bounds of the net, reg, integer, or time, or when the part-select is x or z, shall yield the value x when read, and shall have no effect on the data stored when written.
Part-selects that are partially out of range shall when read return x for the bits that are out of range, and
when written shall only affect the bits that are in range.
Examples:
reg [31:0] big_vect;
reg [0:31] little_vect;
reg [63:0] dword;
integer sel;
The first four if statements show the identity between the two part select constructs. The last one shows an
indexable nature.
initial begin
if ( big_vect[0 +:8] == big_vect[7 : 0]) begin end
if (little_vect[0 +:8] == little_vect[0 : 7]) begin end
if ( big_vect[15 -:8] == big_vect[15 : 8]) begin end
if (little_vect[15 -:8] == little_vect[8 :15]) begin end
if (sel >0 && sel < 8) dword[8sel +:8] = big_vect[7:0];
// Replace the byte selected.*
ADD:
1 先看定义的变量是大端还是小端模式
reg [31:0] big_vect;
reg [0:31] little_vect;
1
2
2 看升序(+:)还是降序(-:)
3 看位宽并进行转换
举例说明:
reg [31:0] big_vect;
reg [0:31] little_vect;
1、首先查看变量big_vect的大小端,记住一点,转化后的与原来的大小端是一样的定义方式
reg [31:0] big_vect;为大端,那么转化后的也一定是大端,形式不变
big_vect[0 +:8]转化后一定是 big_vect[较大的数值 : 较小的数值]
little_vect[0 +:8] 转化后一定是 little_vect[较小的数值 : 较大的数值]
2、其次,看升序(+:)还是降序(-:)
3、最后, 看位宽,进行转换
big_vect [0 +: 8] 从0 开始,升序,位宽为8 ======》》》》》big_vect [7 :0]
little_vect [0 +: 8] 从0 开始,升序,位宽为8 ======》》》》》little_vect [0 :7]
big_vect [15 -: 8] 从15开始,降序,位宽为8 ======》》》》》big_vect [15 :8]
little_vect [15 -: 8] 从15开始,降序,位宽为8 ======》》》》》little_vect [8:15]
再举个例子;在实际项目中遇到的:
output reg [767:0] s_axi_tx_tdata,
genvar i;
generate
for(i=0;i<24;i=i+1)
begin : TDATA_GEN
always @ ( posedge aurora_lclk or negedge rst_n )
begin
if( rst_n == 1’b0 )
s_axi_tx_tdata[i32+:32] <= #U_DLY i;
else if({s_axi_tx_tvalid,s_axi_tx_tready,s_axi_tx_tlast} == 3’b110)
s_axi_tx_tdata[i32+:32] <= #U_DLY s_axi_tx_tdata[i32+:32] + 32’h18;
else if({s_axi_tx_tvalid,s_axi_tx_tready,s_axi_tx_tlast} == 3’b111)
s_axi_tx_tdata[i32+:32] <= #U_DLY s_axi_tx_tdata[i*32+:32] + 32’d16;
else;
end
end
endgenerate
1、找定义
s_axi_tx_tdata的定义形式output reg [767:0] s_axi_tx_tdata,
大端形式(其实管他干个毛呀)要求形式一样就可以了的
2、升序还是降序
s_axi_tx_tdata[i32+:32]为升序
3、看位宽进行转换
s_axi_tx_tdata[i32+:32]形式为s_axi_tx_tdata[较大的数值*:较小的数值],升序,位宽为32且从i32开始
当i=0时,s_axi_tx_tdata[i32+:32] 转化 s_axi_tx_tdata[31:0];
当i=1时,s_axi_tx_tdata[i32+:32] 转化 s_axi_tx_tdata[63:32];
当i=2时,s_axi_tx_tdata[i*32+:32] 转化 s_axi_tx_tdata[95:64];
如果时降序呢
类似:s_axi_tx_tdata[i*32-:32]
OVER