寫在前面
上一篇博文就說到了Verilog的數據類型,其中就常用的就是reg類型以及wire類型,這兩種類型可以定義一位的變量也可以定義多位的變量,其中一位稱之爲標量,多位稱之爲向量,類似於數組。本篇博客主要講述對多位變量的一些操作。
例如:
Verilog 2001修訂版新增的bit位選擇語法:
[<start_bit> +: <width>] // part-select increments from start-bit
[<start_bit> -: <width>] // part-select decrements from start-bit
- 個人微信公衆號: FPGA LAB
正文
標量與變量
Verilog需要表示單個位以及多個位的組。例如,一個單bit時序元件是一個觸發器。然而一個16位的時序元件是一個可以容納16位的寄存器。爲此,Verilog有標量和矢量網以及變量。
一個沒有指定範圍的net或reg聲明被認爲是1位寬,是一個標量。如果指定了範圍,那麼net或reg就變成了一個多比特的實體,稱爲向量。
wire o_nor; // single bit scalar net
wire [7:0] o_flop; // 8-bit vector net
reg parity; // single bit scalar variable
reg [31:0] addr; // 32 bit vector variable to store address
範圍提供了在一個向量中尋址單個位的能力。向量中最高位應該被指定爲範圍內的左手值,而向量中最低位應該被指定在右手邊。
wire [msb:lsb] name;
integer my_msb;
wire [15:0] priority; // msb = 15, lsb = 0
wire [my_msb: 2] prior; // illegal
在上面的例子中,將創建一個16位寬的網,稱爲優先級。注意,msb和Isb應該是一個常量表達式,不能用變量代替。
注:msb以及lsb可以是任何整數值–正負或零,而且Isb的值可以大於、等於或小於msb的值。但爲了保持風格統一,也就是左邊的值要比右邊的值大,所以不建議lsb大於或等於msb.
位選擇
向量中的任意位都可以被單獨選擇,並且可以對其單獨賦值。
如:
reg [7:0] addr; // 8-bit reg variable [7, 6, 5, 4, 3, 2, 1, 0]
addr [0] = 1; // assign 1 to bit 0 of addr
addr [3] = 0; // assign 0 to bit 3 of addr
操作後的示意圖:
但不能超出向量索引範圍:
addr [8] = 1; // illegal : bit8 does not exist in addr
能單個位選擇,當然也能範圍選擇,也即連續選擇相鄰的多位進行賦值等操作。
例如:
reg [31:0] addr;
addr [23:16] = 8'h23; // bits 23 to 16 will be replaced by the new value 'h23 -> constant part-select
上面多位選擇,採用的是常量作爲索引值。
還可以使用如下的方式:
[<start_bit> +: <width>] // part-select increments from start-bit
[<start_bit> -: <width>] // part-select decrements from start-bit
擁有一個可變的部分選擇,可以在循環中有效地使用它來選擇矢量的部分。雖然起始位可以改變,但寬度必須是恆定的。
例如:
module des;
reg [31:0] data;
int i;
initial begin
data = 32'hFACE_CAFE;
for (i = 0; i < 4; i++) begin
$display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
end
$display ("data[7:0] = 0x%0h", data[7:0]);
$display ("data[15:8] = 0x%0h", data[15:8]);
$display ("data[23:16] = 0x%0h", data[23:16]);
$display ("data[31:24] = 0x%0h", data[31:24]);
end
endmodule
仿真結果:
ncsim> run
data[8*0 +: 8] = 0xfe // ~ data [8*0+8 : 8*0]
data[8*1 +: 8] = 0xca // ~ data [8*1+8 : 8*1]
data[8*2 +: 8] = 0xce // ~ data [8*2+8 : 8*2]
data[8*3 +: 8] = 0xfa // ~ data [8*3+8 : 8*3]
data[7:0] = 0xfe
data[15:8] = 0xca
data[23:16] = 0xce
data[31:24] = 0xfa
ncsim: *W,RNQUIE: Simulation is complete.
常見錯誤
舉例:
module tb;
reg [15:0] data;
initial begin
$display ("data[0:9] = 0x%0h", data[0:9]); // Error : Reversed part-select index expression ordering
end
endmodule
這個常見的錯誤,就是混用msb以及lsb的風格導致的,再次強調,統一風格,msb在做,lsb在右!
參考資料
交個朋友
-
個人微信公衆號:FPGA LAB
-
知乎:李銳博恩