Verilog設計技巧例項及實現
1 引言
最近在刷HDLBits的過程中學習了一些Verilog的設計技巧,在這裡予以整理。部分操作可能降低程式碼的可讀性和提高Debug的難度,請大家根據實際情況進行使用。
2 目錄
2.1 casez
例:建立八位輸入訊號的優先編碼器。給定一個8位向量,輸出向量中第一個為1的位。如果輸入向量沒有高位,則報告0。例如,輸入8'b10010000應該輸出3'd4。
這裡我們若用case語句來實現,共有256個case,可以用指令碼生成,但在這裡我們介紹一種基於casez的解決方案,可以將256個case降低為9個item。在casez中,值為z的位將被忽視比較。因此一些輸入(例如4'b1111)將匹配多個case item,選擇第一個匹配項。同時,也可以用?代表忽視比較的項,意義與z相同。程式碼如下:
module top_module (
input [7:0] in,
output reg [2:0] pos );
always@(*)begin
casez(in)
8'bzzzzzzz1:begin//z不予比較
pos = 3'd0;
end
8'bzzzzzz10:begin
pos = 3'd1;
end
8'bzzzzz100:begin
pos = 3'd2;
end
8'bzzzz1000:begin
pos = 3'd3;
end
8'bzzz10000:begin
pos = 3'd4;
end
8'bzz100000:begin
pos = 3'd5;
end
8'bz1000000:begin
pos = 3'd6;
end
8'b10000000:begin
pos = 3'd7;
end
default:begin
pos = 3'd0;
end
endcase
end
endmodule
圖1 結果時序圖
2.2 generate for例項化重複模組
例:已有名為bcd_fadd的一位BCD全加器模組,它將兩個BCD數字a[3:0],b[3:0]加起來併產生和sum[3:0]及進位cout。現需例項化100個bcd_fadd以建立100位BCD全加器,實現將兩個100位BCD數字a[99:0],b[99:0]以及進位訊號cin相加,產生一個100位的和sum[99:0]及進位cout。
在這裡我們可以分割為一個以cin為進位的全加器以及99個重複的以cout_inter為進位的全加器模組,因此可以用generatefor生成重複模組。程式碼如下:
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
wire [99:0] cout_inter;//中間進位值cout
generate
genvar i;
for(i = 0; i <= 99; i++)begin:adder//adder指的是自定義的模組名
if(i==0)begin
bcd_fadd u_bcd_fadd(
.a (a[3:0]),
.b (b[3:0]),
.cin (cin),
.cout (cout_inter[0]),
.sum (sum[3:0])
);
end
else begin
bcd_fadd ui_bcd_fadd(
.a (a[4*i+3:4*i]),
.b (b[4*i+3:4*i]),
.cin (cout_inter[i-1]),
.cout (cout_inter[i]),
.sum (sum[4*i+3:4*i])
);
end
end
endgenerate
assign cout = cout_inter[99];
endmodule
2.3 &、|及^的使用
例:建立一個四輸入(in[3:0])的組合電路,有3個輸出:4位輸入訊號的與out_and、4位輸入訊號的或out_or及4位輸入訊號的異或out_xor
這裡我們可以規約運算子簡單實現,程式碼如下:
module top_module(
input [3:0] in,
output out_and,
output out_or,
output out_xor
);
assign out_and = ∈
assign out_or = |in;
assign out_xor = ^in;
endmodule
圖2 結果時序圖
---
原創教程,轉載請註明出處
參考資料:HDLBits