文章目錄
對讀者的假設
已經掌握:
- 可程式化邏輯基礎
- Verilog HDL基礎
- 使用Verilog設計的Quartus II入門指南
- 使用Verilog設計的ModelSIm入門指南
內容1 算術電路
Verilog HDL中,+、-、*、/、%都是可以綜合的,其消耗的資源視器件資源不同而不同。譬如:+、-都會被綜合成Adder,每一位大約消耗一個LE(Cyclone II);*則會被綜合成乘法器,若器件內含有乘法器,則底層被映射成乘法器,否則使用LE實現。下面慢慢討論。
1.1 加法運算 +
代碼1.1 加法運算(可綜合)
module arithmetic( input [7 :0] iA, input [7 :0] iB, output [8 :0] oAdd );assign oAdd = iA + iB;endmodule
圖1.1 加法運算綜合的RTL視圖及資源消耗
1.1 所示加法運算被綜合成ADDER,其資源消耗約1 LE/位(對應Cyclone II的LUT-4結構的LE)。
代碼1.2 加法運算的testbench(不可綜合,僅用於模擬)
`timescale 1ns/1nsmodule arithmetic_tb;reg [7:0] i_a = 8'b1011_0111;reg [7:0] i_b = 8'b0100_1000;wire [8:0] o_add;initial #100 $stop;arithmetic arithmetic_inst( .iA (i_a), .iB (i_b), .oAdd (o_add) );endmodule
圖1.2 加法運算的功能模擬
1.2 乘法運算 *
代碼1.3 乘法運算代碼
module arithmetic( input [7:0] iA, input [7:0] iB, output [15:0] oMul );assign oMul = iA * iB;endmodule
圖1.3 乘法運算直接調用lpm_mult
圖1.4 乘法運算綜合的RTL視圖及資源消耗
觀察綜合後的結果,我們發現,Cylone II的x被直接映射到了乘法器。此處為Embedded Multiplier 9-bit elements,實際上Cyclone II嵌入的乘法器為18位的,每一個乘法器又可以拆成2個9位的乘法器使用。
代碼1.4 乘法運算的testbench
`timescale 1ns/1nsmodule arithmetic_tb;reg [7:0] i_a = 8'b1011_0111;reg [7:0] i_b = 8'b0100_1000;wire [15:0] o_mul;initial #100 $stop;arithmetic arithmetic_inst( .iA (i_a), .iB (i_b), .oMul (o_mul) );endmodule
圖1.5 乘法運算的功能模擬波形
1.3 除法運算 /
代碼1.5 除法運算
module arithmetic( input [7:0] iA, input [7:0] iB, output [7:0] oDiv );assign oDiv = iA / iB;endmodule
綜合之後,我們發現除法運算是直接調用的lpm_divide來實現的。
圖1.5 除法運算直接調用lpm_divide
圖1.6 除法運算綜合的RTL視圖及資源消耗
由圖1.6所示,除法運算雖然可以直接調用宏,但是其資源消耗也是非常巨大,大約每一位除法消耗10個LE。
代碼1.6 除法運算的testbench
`timescale 1ns/1nsmodule arithmetic_tb;reg [7:0] i_a = 8'b1011_0111;reg [7:0] i_b = 8'b0100_1000;wire [7:0] o_div;initial #100 $stop;arithmetic arithmetic_inst( .iA (i_a), .iB (i_b), .oDiv (o_div) );endmodule
圖1.7 除法運算的功能模擬波形
1.4 取餘運算 %
代碼1.7 取餘運算
module arithmetic( input [7:0] iA, input [7:0] iB, output [7:0] oMod );assign oMod = iA % iB;endmodule
同除法運算一樣,取餘運算也是直接調用的lpm_divide來實現的。
圖1.8 取餘運算直接調用宏實現
圖1.9 取餘運算綜合的RTL視圖及資源消耗
代碼1.8 取餘運算的testbench
`timescale 1ns/1nsmodule arithmetic_tb;reg [7:0] i_a = 8'b1011_0111;reg [7:0] i_b = 8'b0100_1000;wire [7:0] o_mod;initial #100 $stop;arithmetic arithmetic_inst( .iA (i_a), .iB (i_b), .oMod (o_mod) );endmodule
圖1.10 取餘運算的功能模擬波形
2 資料比較子
代碼2.1 資料比較子(可綜合)
module arithmetic( input [3:0] iA, input [3:0] iB, output oEQ, // 等於 output oNEQ, // 不等於 output oGT, // 大於 output oGT_EQ, // 大於等於 output oLT, // 小於 output oLT_EQ // 小於等於);assign oEQ = (iA == iB), oNEQ = (iA != iB), oGT = (iA > iB), oGT_EQ = (iA >= iB), oLT = (iA < iB), oLT_EQ = (iA <= iB);endmodule
觀察第12~17行,資料比較子的描述方法與C語言強式一致性。
assign oEQ = (iA == iB), oNEQ = (iA != iB), oGT = (iA > iB), oGT_EQ = (iA >= iB), oLT = (iA < iB), oLT_EQ = (iA <= iB);
圖2.1 綜合後的資料比較子的RTL視圖
代碼2.2 資料比較子的testbench(不可綜合,僅用於模擬)
`timescale 1ns/1nsmodule arithmetic_tb;reg [3:0] i_a;reg [3:0] i_b;wire o_eq, o_neq, o_gt, o_gt_eq, o_lt, o_lt_eq;initial begin i_a = 5; i_b = 5; #20 i_a = 6; #20 i_a = 4; #20 $stop;endarithmetic arithmetic_inst( .iA (i_a), .iB (i_b), .oEQ (o_eq), .oNEQ (o_neq), .oGT (o_gt), .oGT_EQ (o_gt_eq), .oLT (o_lt), .oLT_EQ (o_lt_eq) );endmodule
圖2.2 資料比較子的功能模擬波形
3 移位元運算
Veirlog HDL 2001支援邏輯移位及算術移位。
3.1 邏輯移位
代碼3.1 邏輯移位(可綜合)
module arithmetic( input [7:0] iA, input [2:0] iBit, // 移位的位元 0~7 output [7:0] oSLL, // 邏輯左移 output [7:0] oSRL // 邏輯右移); assign oSLL = (iA << iBit), oSRL = (iA >> iBit); endmodule
第8~9行,邏輯移位的符號和C語言也是一致的:>>(邏輯右移,shift right logical);<<(邏輯左移,shift left logical)。assign關鍵字後,若有多條語句,則可以使用逗號隔開;也可以分開使用兩個assign語句來描述。
assign oSLL = (iA << iBit), oSRL = (iA >> iBit);
圖3.1 邏輯移位的RTL視圖
代碼3.2 邏輯移位的testbench
`timescale 1ns/1nsmodule arithmetic_tb;reg [7:0] i_a = 8'b1011_0111;reg [2:0] i_bit = 0;wire [7:0] o_sll, o_srl;initial while(i_bit<7) #20 i_bit = i_bit + 1'b1;initial #160 $stop;arithmetic arithmetic_inst( .iA (i_a), .iBit (i_bit), .oSLL (o_sll), .oSRL (o_srl) );endmodule
第3~4行,在聲明reg類型的訊號時,同時賦初值。
reg [7:0] i_a = 8'b1011_0111;reg [2:0] i_bit = 0;
第6~7行,同一類型及等位寬的訊號,可以使用逗號隔開聲明,也可以分開聲明。
wire [7:0] o_sll, o_srl;
第9行,採用while語句來產生激勵,其用法與C語言一致。
initial while(i_bit<7) #20 i_bit = i_bit + 1'b1;
右鍵所需觀察的訊號,選擇Radix>Unsigned,以無符號十進位形式查看i_bit。3.2所示。
圖3.2 以無符號十進位形式查看i_bit
圖3.3 邏輯移位的功能模擬波形
3.2 算術移位
算術移位與邏輯移位的區別見參考3。
代碼3.3 有符號數的邏輯移位與算術移位(可綜合)
module arithmetic( input signed [7:0] iA, input [2:0] iBit, // 移位的位元 0~7 output signed [7:0] oSLL, // 邏輯左移 output signed [7:0] oSRL, // 邏輯右移 output signed [7:0] oASL, // 算術左移 output signed [7:0] oASR // 算術右移); assign oSLL = (iA << iBit), oSRL = (iA >> iBit), oASL = (iA <<< iBit), oASR = (iA >>> iBit);endmodule
第2~7行,移位的位元被聲明成無符號數,而移位的資料及其結果被聲明成有符號數。
input signed [7:0] iA, input [2:0] iBit, // 移位的位元 0~7 output signed [7:0] oSLL, // 邏輯左移 output signed [7:0] oSRL, // 邏輯右移 output signed [7:0] oASL, // 算術左移 output signed [7:0] oASR // 算術右移
第10~13行,與邏輯移位不同,算術移位的運算子是:<<<(算術左移,arithmetic shift left);>>>(算術右移,arithmetic shift right)。
assign oSLL = (iA << iBit), oSRL = (iA >> iBit), oASL = (iA <<< iBit), oASR = (iA >>> iBit);
圖3.4 有符號數的邏輯移位與算術移位的RTL視圖
代碼3.4 有符號數的邏輯移位與算術移位的testbench(不可綜合,僅用於模擬)
`timescale 1ns/1nsmodule arithmetic_tb;reg signed [7:0] i_a = 8'sb1011_0111;reg signed [2:0] i_bit = 0;wire signed [7:0] o_sll, o_srl, o_asl, o_asr;initial while(i_bit<7) #20 i_bit = i_bit + 1'b1;initial #160 $stop;arithmetic arithmetic_inst( .iA (i_a), .iBit (i_bit), .oSLL (o_sll), .oSRL (o_srl), .oASL (o_asl), .oASR (o_asr) );endmodule
全選所有訊號, 右鍵選擇Radix>Binary,以二進位形式查看。3.5所示。
圖3.5 以二進位形式查看所有訊號
圖3.6 有符號數的邏輯移位與算術移位的功能模擬波形
小結:算術左移和邏輯左移的效果一致;算術右移移出的資料填充的是符號位,而邏輯右移移出的資料填充的是0。
輔助閱讀
1. Altera.Recommended HDL Coding Styles
參考
1. Signed Arithmetic in Verilog 2001 – Opportunities and Hazards
2. http://iroi.seu.edu.cn/books/asics/Book2/CH11/CH11.03.htm
3. bsdc.算術移位與邏輯移位有什麼區別?
另見
[與艾米一起學FPGA/SOPC].[邏輯實驗文檔連載計劃]