99re热视频这里只精品,久久久天堂国产精品女人,国产av一区二区三区,久久久精品成人免费看片,99久久精品免费看国产一区二区三区

Verilog 帶參數(shù)例化

2022-05-17 11:29 更新

關(guān)鍵詞: defparam,參數(shù),例化,ram

當(dāng)一個(gè)模塊被另一個(gè)模塊引用例化時(shí),高層模塊可以對低層模塊的參數(shù)值進(jìn)行改寫。這樣就允許在編譯時(shí)將不同的參數(shù)傳遞給多個(gè)相同名字的模塊,而不用單獨(dú)為只有參數(shù)不同的多個(gè)模塊再新建文件。

參數(shù)覆蓋有 2 種方式:

  1. 使用關(guān)鍵字 ?defparam?
  2. 帶參數(shù)值模塊例化

defparam 語句

可以用關(guān)鍵字 ?defparam? 通過模塊層次調(diào)用的方法,來改寫低層次模塊的參數(shù)值。

例如對一個(gè)單口地址線和數(shù)據(jù)線都是 4bit 寬度的 ?ram? 模塊的 ?MASK? 參數(shù)進(jìn)行改寫:

//instantiation
defparam     u_ram_4x4.MASK = 7 ;
ram_4x4    u_ram_4x4
    (
        .CLK    (clk),
        .A      (a[4-1:0]),
        .D      (d),
        .EN     (en),
        .WR     (wr),    //1 for write and 0 for read
        .Q      (q)    );

?ram_4x4? 的模型如下:

module  ram_4x4
    (
     input               CLK ,
     input [4-1:0]       A ,
     input [4-1:0]       D ,
     input               EN ,
     input               WR ,    //1 for write and 0 for read
     output reg [4-1:0]  Q    );
 
    parameter        MASK = 3 ;
 
    reg [4-1:0]     mem [0:(1<<4)-1] ;
    always @(posedge CLK) begin
        if (EN && WR) begin
            mem[A]  <= D & MASK;
        end
        else if (EN && !WR) begin
            Q       <= mem[A] & MASK;
        end
    end
 
endmodule

對此進(jìn)行一個(gè)簡單的仿真,testbench 編寫如下:

`timescale 1ns/1ns
 
module test ;
    parameter    AW = 4 ;
    parameter    DW = 4 ;
 
    reg                  clk ;
    reg [AW:0]           a ;
    reg [DW-1:0]         d ;
    reg                  en ;
    reg                  wr ;
    wire [DW-1:0]        q ;
 
    //clock generating
    always begin
        #15 ;     clk = 0 ;
        #15 ;     clk = 1 ;
    end
 
    initial begin
        a         = 10 ;
        d         = 2 ;
        en        = 'b0 ;
        wr        = 'b0 ;
        repeat(10) begin
            @(negedge clk) ;
            en     = 1'b1;
            a      = a + 1 ;
            wr     = 1'b1 ;  //write command
            d      = d + 1 ;
        end
        a         = 10 ;
        repeat(10) begin
            @(negedge clk) ;
            a      = a + 1 ;
            wr     = 1'b0 ;  //read command
        end
    end // initial begin
 
    //instantiation
    defparam     u_ram_4x4.MASK = 7 ;
    ram_4x4    u_ram_4x4
    (
        .CLK    (clk),
        .A      (a[AW-1:0]),
        .D      (d),
        .EN     (en),
        .WR     (wr),    //1 for write and 0 for read
        .Q      (q)
     );
 
    //stop simulation
    initial begin
        forever begin
            #100;
            if ($time >= 1000)  $finish ;
        end
    end
 
endmodule // test

仿真結(jié)果如下:

圖中黃色部分,當(dāng)?shù)刂返谝淮螢?nbsp;c 時(shí)寫入數(shù)據(jù) 4, 當(dāng)?shù)诙蔚刂窞?nbsp;c 時(shí)讀出數(shù)據(jù)為 4;可知此時(shí) ?ram? 行為正確,且 ?MASK? 不為 3。 因?yàn)?nbsp;?ram? 的 Q 端 bit2 沒有被屏蔽。

當(dāng)?shù)谝淮蔚刂窞?nbsp;1 時(shí)寫入數(shù)據(jù)為 9,第二次地址為 1 時(shí)讀出的數(shù)據(jù)卻是 1,因?yàn)榇藭r(shí) ?MASK? 為 7,?ram? 的 Q 端信號 bit3 被屏蔽。由此可知,?MASK? 參數(shù)被正確改寫。


帶參數(shù)模塊例化

第二種方法就是例化模塊時(shí),將新的參數(shù)值寫入模塊例化語句,以此來改寫原有 ?module? 的參數(shù)值。

例如對一個(gè)地址和數(shù)據(jù)位寬都可變的 ?ram? 模塊進(jìn)行帶參數(shù)的模塊例化:

ram #(.AW(4), .DW(4))
    u_ram
    (
        .CLK    (clk),
        .A      (a[AW-1:0]),
        .D      (d),
        .EN     (en),
        .WR     (wr),    //1 for write and 0 for read
        .Q      (q)
     );

?ram? 模型如下:

module  ram
    #(  parameter       AW = 2 ,
        parameter       DW = 3 )
    (
        input                   CLK ,
        input [AW-1:0]          A ,
        input [DW-1:0]          D ,
        input                   EN ,
        input                   WR ,    //1 for write and 0 for read
        output reg [DW-1:0]     Q
     );
 
    reg [DW-1:0]         mem [0:(1<<AW)-1] ;
    always @(posedge CLK) begin
        if (EN && WR) begin
            mem[A]  <= D ;
        end
        else if (EN && !WR) begin
            Q       <= mem[A] ;
        end
    end
 
endmodule

仿真時(shí),只需在上一例的 testbench 中,將本次例化的模塊 ?u_ram? 覆蓋掉 ?u_ram_4x4?, 或重新添加之即可。

仿真結(jié)果如下。由圖可知,?ram? 模塊的參數(shù) ?AW? 與 ?DW? 均被改寫為 4, 且 ?ram? 行為正確。


區(qū)別與建議

  1. 和模塊端口實(shí)例化一樣,帶參數(shù)例化時(shí),也可以不指定原有參數(shù)名字,按順序進(jìn)行參數(shù)例化,例如 ?u_ram? 的例化可以描述為:
  2. ram #(4, 4)   u_ram (......) ;
  3. 當(dāng)然,利用 ?defparam? 也可以改寫模塊在端口聲明時(shí)聲明的參數(shù),利用帶參數(shù)例化也可以改寫模塊實(shí)體中聲明的參數(shù)。例如 ?u_ram? 和 ?u_ram_4x4? 的例化分別可以描述為:
  4. defparam     u_ram.AW = 4 ;
    defparam     u_ram.DW = 4 ;
    ram   u_ram(......);
    ram_4x4  #(.MASK(7))    u_ram_4x4(......);
  5. 那能不能混合使用這兩種模塊參數(shù)改寫的方式呢?當(dāng)然能!前提是所有參數(shù)都是模塊在端口聲明時(shí)聲明的參數(shù)或參數(shù)都是模塊實(shí)體中聲明的參數(shù),例如 ?u_ram? 的聲明還可以表示為(模塊實(shí)體中參數(shù)可自行實(shí)驗(yàn)驗(yàn)證):
  6. defparam     u_ram.AW = 4 ;
    ram #(.DW(4)) u_ram (......);  //也只有我這么無聊才會實(shí)驗(yàn)這種寫法
  7. 那如果一個(gè)模塊中既有在模塊在端口聲明時(shí)聲明的參數(shù),又有在模塊實(shí)體中聲明的參數(shù),那這兩種參數(shù)還能同時(shí)改寫么?例如在 ?ram? 模塊中加入 ?MASK? 參數(shù),模型如下:
  8. module  ram
        #(  parameter       AW = 2 ,
            parameter       DW = 3 )
        (
            input                   CLK ,
            input [AW-1:0]          A ,
            input [DW-1:0]          D ,
            input                   EN ,
            input                   WR ,    //1 for write and 0 for read
            output reg [DW-1:0]     Q    );
     
        parameter            MASK = 3 ;
     
        reg [DW-1:0]         mem [0:(1<<AW)-1] ;
        always @(posedge CLK) begin
            if (EN && WR) begin
                mem[A]  <= D ;
            end
            else if (EN && !WR) begin
                Q       <= mem[A] ;
            end
        end
     
    endmodule

    此時(shí)再用 ?defparam? 改寫參數(shù) ?MASK? 值時(shí),編譯報(bào) ?Error?:

    //都采用defparam時(shí)會報(bào)Error
    defparam     u_ram.AW = 4 ;
    defparam     u_ram.DW = 4 ;
    defparam     u_ram.MASK = 7 ;
    ram   u_ram  (......);
     
    //模塊實(shí)體中parameter用defparam改寫也會報(bào)Error
    defparam     u_ram.MASK = 7 ;
    ram #(.AW(4), .DW(4))   u_ram (......);

    重點(diǎn)來了!?。∪绻阌脦?shù)模塊例化的方法去改寫參數(shù) ?MASK? 的值,編譯不會報(bào)錯(cuò),?MASK? 也將被成功改寫!

    ram #(.AW(4), .DW(4), .MASK(7)) u_ram (......);
    

    可能的解釋為,在編譯器看來,如果有模塊在端口聲明時(shí)的參數(shù),那么實(shí)體中的參數(shù)將視為 ?localparam? 類型,使用 ?defparam? 將不能改寫模塊實(shí)體中聲明的參數(shù)。

    也可能和編譯器有關(guān)系,大家也可以在其他編譯器上實(shí)驗(yàn)。

  9. 建議,對已有模塊進(jìn)行例化并將其相關(guān)參數(shù)進(jìn)行改寫時(shí),不要采用 ?defparam? 的方法。除了上述缺點(diǎn)外,?defparam? 一般也不可綜合。
  10. 而且建議,模塊在編寫時(shí),如果預(yù)知將被例化且有需要改寫的參數(shù),都將這些參數(shù)寫入到模塊端口聲明之前的地方(用關(guān)鍵字井號 ??表示)。這樣的代碼格式不僅有很好的可讀性,而且方便調(diào)試。

點(diǎn)擊這里下載源碼

階段總結(jié)

其實(shí),介紹到這里,大家完全可以用前面學(xué)習(xí)到的 Verilog 語言知識,去搭建硬件電路的小茅草屋。對,是小茅草屋。因?yàn)橛布Z言對應(yīng)實(shí)際硬件電路的這種特殊性,在用 Verilog 建立各種模型時(shí)必須考慮實(shí)際生成的電路是什么樣子的,是否符合實(shí)際要求。有時(shí)候 ?rtl? 仿真能通過,但是最后生成的實(shí)際電路可能會工作異常。

所以,要為你的小茅草屋添磚蓋瓦,還需要再學(xué)習(xí)下進(jìn)階部分。當(dāng)然,進(jìn)階部分也只能讓你的小茅草屋變成硬朗的磚瓦房,能抵擋風(fēng)雪交加,可能遇到地震還是會垮塌。

如果你想鞏固下你的磚瓦房,去建一套別墅,那你需要再學(xué)習(xí)下 Verilog 高級篇知識,例如 ?PLI?(編程語言接口)、?UDP?(用戶自定義原語),時(shí)序約束和時(shí)序分析等,還需要多參與項(xiàng)目工程積累經(jīng)驗(yàn),特別注意一些設(shè)計(jì)技巧,例如低功耗設(shè)計(jì)、異步設(shè)計(jì)等。當(dāng)然學(xué)會用 ?SystemVerilog? 去全面驗(yàn)證,又會讓你的建筑增加一層防護(hù)盾。

但是如果你想把數(shù)字電路、Verilog 所有的知識學(xué)完,去筑一套防炮彈的總統(tǒng)府,那真的是愛莫能助。因?yàn)?,學(xué)海無涯,回頭沒岸哪。

限于篇幅,這里只介紹下進(jìn)階篇。有機(jī)會,高級篇,技巧篇,也一并補(bǔ)上。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號