Verilog設計技巧例項及實現

吃豆熊發表於2021-10-31

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

圖片alt

圖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 = &in;
    assign out_or = |in;
    assign out_xor = ^in;
endmodule

圖片alt

圖2 結果時序圖

---

原創教程,轉載請註明出處

參考資料:HDLBits

相關文章