国产电影一区二区三区,,欧美大片免费观看,伊人久久大香线蕉av,国产日韩成人内射视频

HDLBits練習匯總-03-Verilog語言--模塊層次結構

Module

到目前為止,您已經熟悉了模塊,它是一種通過輸入和輸出端口與外部交互的電路。更大、更復雜的電路是由更小的模塊組成更大的模塊,并將其他部分(如賦值語句和always塊)連接在一起來構建的。這形成了一個層次結構,因為模塊可以包含其他模塊的實例。

下圖顯示了一個非常簡單的帶有子模塊的電路。在本練習中,創建模塊mod_a的一個實例,然后將模塊的三個引腳(in1、in2和out)連接到頂層模塊的三個端口(連接a、b和out)。模塊mod_a是為你提供的-你必須實例化它。

連接模塊時,只有模塊上的端口是重要的。您不需要知道模塊內部的代碼。模塊mod_a的代碼如下所示:

module mod_a ( input in1, input in2, output out );
    // Module body
endmodule

模塊的層次結構是通過在另一個模塊中實例化一個模塊來創建的,只要所有使用的模塊都屬于同一個項目(這樣編譯器就知道在哪里可以找到這個模塊)。一個模塊的代碼不寫入另一個模塊的內部(不同模塊的代碼不嵌套)。

您可以通過端口名稱或端口位置將信號連接到模塊。對于額外的練習,兩種方法都試試。

連接信號到模塊端口有兩種常用的方法將導線連接到端口:按位置按名稱

按位置連接

按照位置將連線連接到端口的語法應該很熟悉,因為它使用類似于c的語法。當實例化一個模塊時,端口根據模塊的聲明從左到右連接。 例如:Mod_a instance1 (wa, wb, wc);這將實例化一個mod_a類型的模塊,并給它一個實例名“instance1”,然后將信號wa(新模塊外部)連接到新模塊的第一個端口(in1), wb連接到第二個端口(in2), wc連接到第三個端口(out)。這種語法的一個缺點是,如果模塊的端口列表改變了,模塊的所有實例化也需要被找到并改變以匹配新的模塊。

按名字連接

通過名稱將信號連接到模塊的端口,這樣即使端口列表發生變化,線路也能保持正確連接。但是,這種語法更加冗長。

mod_a instance2 (.out (wc) .in1 (wa) .in2 (wb));

上面這行代碼實例化了一個名為“instance2”的mod_a類型的模塊,然后將信號wa(模塊外部)連接到名為in1的端口,wb連接到名為in2的端口,wc連接到名為out的端口。請注意,端口的順序在這里是不相關的,因為無論它在子模塊的端口列表中的位置如何,都將連接到正確的名稱。還要注意此語法中緊鄰端口名的句點。

module top_module ( input a, input b, output out );

通過端口名稱或端口位置將信號連接到模塊。答案:通過位置連接

通過名字連接

module top_module ( input a, input b, output out );
    mod_a instance2 ( 
        .out(out), 
        .in1(a), 
        .in2(b) 
    );
endmodule

按位置進行模塊連接

這個問題類似于上一個。給定一個名為mod_a的模塊,該模塊按此順序有2個輸出和4個輸入。您必須按位置將6個端口連接到頂級模塊的端口out1、out2、a、b、c和d,按此順序。 你會得到以下模塊:

module mod_a ( output, output, input, input, input, input );

Module Declaration

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);

答案:

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a inst1_mod_a( out1, out2, a, b, c, d );
endmodule

按名字進行模塊連接

這個問題類似前兩個。給定一個名為mod_a的模塊,該模塊按一定順序有2個輸出和4個輸入。你必須將這6個端口按名稱連接到你的頂級模塊的端口:

你會得到以下模塊:

module mod_a ( output out1, output out2, input in1, input in2, input in3, input in4);

Module Declaration

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);

答案:

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);
    mod_a u_mod_a( 
        .out1(out1), 
        .out2(out2),
        .in1(a), 
        .in2(b),
        .in3(c), 
        .in4(d)
    );
endmodule

Module shift(移位寄存器)

你會得到一個模塊my_dff,它有兩個輸入和一個輸出(它實現了D觸發器)。實例化它們中的三個,然后將它們鏈在一起,生成一個長度為3的移位寄存器。clk端口需要連接到所有實例。

module my_dff ( input clk, input d, output q );

注意,要建立內部連接,需要聲明一些連接。在命名連線和模塊實例時要小心:名稱必須唯一。

Module Declaration

module top_module ( input clk, input d, output q );

答案:按位置:

module top_module ( input clk, input d, output q );
    
    wire q1,q2;
    
    my_dff u1_my_dff( clk, d, q1 );
    my_dff u2_my_dff( clk, q1, q2 );
    my_dff u3_my_dff( clk, q2, q );
endmodule

按名字:

module top_module ( input clk, input d, output q );
    
    wire q1,q2;
    
    my_dff u1_my_dff( .clk(clk), .d(d),  .q(q1) );
    my_dff u2_my_dff( .clk(clk), .d(q1), .q(q2) );
    my_dff u3_my_dff( .clk(clk), .d(q2), .q(q ));
endmodule

Module shift8(八位移位寄存器)

這個練習是module_shift的延伸。模塊端口不再是單一的引腳,我們現在有了以矢量作為端口的模塊,你將把線矢量連接到這些模塊上,而不是普通的線。與Verilog中的其他地方一樣,端口的向量長度不必與連接它的電線匹配,但這將導致向量的零填充或結構。本練習不使用向量長度不匹配的連接。

您會得到一個模塊my_dff8,它有兩個輸入和一個輸出(它實現了一組8d觸發器)。實例化其中三個,然后將它們鏈在一起,生成一個長度為3的8位寬移位寄存器。此外,創建一個4對1多路復用器(未提供),根據sel[1:0]選擇輸出什么:輸入d的值,在第一個、第二個或第三個d觸發器之后。(本質上,sel選擇輸入延遲的周期,從0到3個時鐘周期。)

提供給你的模塊是:module my_dff8 ( input clk, input [7:0] d, output [7:0] q );沒有提供復用器。一種可能的編寫方法是在always塊中使用case語句。

Module Declaration

module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);

答案:

module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);
    
    wire [7:0] q1,q2,q3;
	my_dff8 (clk,d, q1 );
	my_dff8 (clk,q1, q2 );
    my_dff8 (clk,q2, q3 );
    always@(*)begin
        case(sel)
            0: q = d;
            1: q = q1;
            2: q = q2;
            3: q = q3;
        endcase
    end
endmodule

加法器模塊1

您將得到一個模塊add16,它執行一個16位的添加操作。實例化其中兩個以創建一個32位加法器。一個add16模塊計算相加結果的低16位,而第二個add16模塊在收到第一個加法器的進位后計算結果的高16位。您的32位加法器不需要處理進位(假設0)或進位(忽略),但內部模塊需要正確工作。(換句話說,add16模塊執行16位a + b + cin,而您的模塊執行32位a + b)。 如圖所示將這些模塊連接在一起:module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

Module Declaration

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);

答案(按名字連接比較常用,所以這里只給出按名字的結果):

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire cout_to_cin;
    add16 u_add16_l( .a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(cout_to_cin));
    add16 u_add16_h( .a(a[31:16]), .b(b[31:16]), .cin(cout_to_cin), .sum(sum[31:16]), .cout());
endmodule

加法器模塊2

在本練習中,您將創建一個具有兩個層次結構的電路。您的top_module將實例化add16的兩個副本(提供的),每個副本將實例化add1的16個副本(您必須編寫add1)。因此,必須編寫兩個模塊:top_module和add1。

與module_add類似,您將得到一個執行16位添加的模塊add16。您必須實例化其中兩個以創建一個32位加法器。一個add16模塊計算添加結果的低16位,而第二個add16模塊計算結果的高16位。您的32位加法器不需要處理進位(假設0)或進位(忽略)。 按照下圖將add16模塊連接在一起。提供的模塊add16有以下聲明:module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );在每個add16中,將實例化16個完整的加法器(模塊add1,未提供)以實際執行添加。你必須編寫完整的加法器模塊,聲明如下:module add1 ( input a, input b, input cin, output sum, output cout );

綜上所述,本設計主要分為三個模塊:

  • top_module -你的頂級模塊。
  • add16 -16位加法器模塊。
  • add1 - 1位全加法器模塊。

Module Declaration

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);

答案:

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
    wire cout_to_cin;
    add16 u_add16_l( .a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(cout_to_cin));
    add16 u_add16_h( .a(a[31:16]), .b(b[31:16]), .cin(cout_to_cin), .sum(sum[31:16]), .cout());

endmodule

module add1( input a, input b, input cin,   output sum, output cout );
	assign sum = a ^ b ^ cin;
    assign cout = a&b | a&cin | b&cin;
// Full adder module here
endmodule

進位選擇加法器

紋波進位加法器的一個缺點(前面的練習)是,加法器計算進位的延遲(在最壞的情況下,從進位算起)相當緩慢,第二級加法器直到第一級加法器完成后才能開始計算其進位。這使得加法器變慢。一個改進是進位選擇加法器,如下所示。第一級加法器和之前一樣,但是我們復制了第二級加法器,一個假設進位為0,一個假設進位為1,然后使用快速的2比1多路復用器來選擇哪個結果恰好是正確的。 在本練習中,提供了與前一個練習相同的add16模塊,該模塊對兩個16位數字進行進位運算,并生成一個進位和16位和。您必須實例化其中三個以使用您自己的16位2- 1多路復用器來構建進位選擇加法器。 如下圖所示將這些模塊連接在一起。提供的模塊add16有以下聲明:

module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

Module Declaration

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);

答案:

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
	wire cout_to_cin;
    wire [15:0]sum_0;
    wire [15:0]sum_1;
    add16 u_add16_1( .a(a[15:0]), .b(b[15:0]), .cin(0), .sum(sum[15:0]), .cout(cout_to_cin));
    add16 u_add16_2( .a(a[31:16]), .b(b[31:16]), .cin(0), .sum(sum_0), .cout());
    add16 u_add16_3( .a(a[31:16]), .b(b[31:16]), .cin(1), .sum(sum_1), .cout());
    always@(*)begin
        case(cout_to_cin)
            0: sum[31:16]= sum_0;
            1: sum[31:16]= sum_1;
        endcase
    end
endmodule

加減法器

加-減法器可以由加法器建立,可以選擇對一個輸入取反,這相當于將輸入取反,然后加1。最終得到的電路可以進行兩種運算:(a + b + 0)和(a + ~b + 1)。 構建下面的加減器。 你提供了一個16位加法器模塊,你需要實例化兩次:

module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

當sub為1時,使用一個32位寬的異或門來反置b輸入。(這也可以看作是b[31:0] xor與子復制32次。看到復制操作符)。也連接子輸入到加法器的進位。

Module Declaration

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);

答案:

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire cout_to_cin;
    wire [31:0] b1 ={32{sub}}^b;
    add16 u_add16_1( .a(a[15:0]), .b(b1[15:0]), .cin(sub), .sum(sum[15:0]), .cout(cout_to_cin));
    add16 u_add16_2( .a(a[31:16]), .b(b1[31:16]), .cin(cout_to_cin), .sum(sum[31:16]), .cout());
endmodule
聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 17
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧