HDLBits刷题合集—4 Modules: Hierarchy

HDLBits刷题合集—4 Modules:Hierarchy

HDLBits-17 Module
Problem Statement
下图显示了一个带有子模块的非常简单的电路。在本练习中,创建模块mod_a的一个实例,然后将模块的三个引脚(in1、in2和out)连接到顶层模块的三个端口(连接a、b和out)。mod_a模块已经为你提供,你使用时必须实例化它。

在连接模块时,只有模块上的端口是重要的。不需要知道模块内部的代码。模块mod_a的代码如下:
module mod_a ( input in1, input in2, output out );
// Module body
endmodule

在这里插入图片描述
模块的层次结构是通过在另一个模块中实例化一个模块来创建的,只要使用的所有模块都属于同一个工程(这样编译器就知道在哪里可以找到模块)。一个模块的代码不能写在另一个模块的内部(即不同模块的代码不嵌套)。
可以通过端口名端口位置将信号连接到模块。可以额外的练习,尝试这两种方法。

HDLBits刷题合集—4 Modules: Hierarchy_第1张图片
将信号连接到模块端口
有两种常用的方法将线路连接到端口:按位置按名称

按位置
按照位置将连接线连接到端口的语法应该很熟悉,因为它使用类似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 );

    //By name
    mod_a instance1 (.out(out), .in1(a), .in2(b));
    
endmodule

HDLBits-18 Module positoin
Problem Statement
这个问题与前一个问题类似。给定一个名为mod_a的模块,有2个输出和4个输入。你必须按位置将6个端口连接到顶层模块的端口out1、out2、a、b、c和d,按照这个顺序。
给你以下模块:
module mod_a ( output, output, input, input, input, input );

HDLBits刷题合集—4 Modules: Hierarchy_第2张图片
代码如下:

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

    mod_a name1( out1, out2, a, b, c, d);
 
endmodule

HDLBits-19 Module name
Problem Statement
这个问题还是与第17个问题类似。给定一个名为mod_a的模块,它有2个输出和4个输入,按某种顺序排列。你必须通过名称将6个端口连接到顶层模块的端口:

Port in mod_a Port in top_module
output out1 out1
output out1 out2
input in1 a
input in2 b
input in3 c
input in4 d

给定的模块是:
module mod_a ( output out1, output out2, input in1, input in2, input in3, input in4);

HDLBits刷题合集—4 Modules: Hierarchy_第3张图片
代码如下:

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

    mod_a name2 (.out1(out1), .out2(out2), .in1(a), .in2(b), .in3(c), .in4(d));
    
endmodule

HDLBits-20 Module shift
Problem Statement
给定一个模块my_dff,有两个输入和一个输出(实现一个D触发器)。实例化模块my_dff三次,然后将它们连接在一起,形成长度为3的移位寄存器。clk端口需要连接到所有实例。
给定的模块是:
module my_dff ( input clk, input d, output q );
注意要进行内部连接,需要声明一些wire。在对wire和模块实例进行命名时要小心:这些名称必须是惟一的。

HDLBits刷题合集—4 Modules: Hierarchy_第4张图片
代码如下:

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

    wire q1,q2;
    
    my_dff dff1( clk, d, q1);
    my_dff dff2( clk, q1, q2);
    my_dff dff3( clk, q2, q);
    
endmodule

HDLBits-21 Module shift8
Problem Statement
这个练习是上一题module_shift的延申。模块端口不再是单一的引脚,而是以向量为端口,你可以将线向量而不是普通的导线连接到模块上。

给定一个模块my_dff8,它有两个输入和一个输出(实现一个8位的D触发器)。实例化my_dff8三次,然后将它们连接在一起,形成一个长度为3的8位宽移位寄存器。

此外,创建一个4选1多路复用选择器(没有提供),它根据sel[1:0]选择输出什么:在输入d处的值,在第一个D触发器之后、第二个D触发器之后或第三个D触发器之后。(本质上,sel选择多少周期来延迟输入,从0到3个时钟周期。)

给定的模块是:
module my_dff8 ( input clk, input [7:0] d, output [7:0] q );

HDLBits刷题合集—4 Modules: Hierarchy_第5张图片
代码如下:

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 dff1 (clk, d, q1);
    my_dff8 dff2 (clk, q1, q2);
    my_dff8 dff3 (clk, q2, q3);
    
    always @(*) 
        begin
            case(sel)
                2'h0: q = d;
                2'h1: q = q1;
                2'h2: q = q2;
                2'h3: q = q3;
            endcase
        end
        
endmodule

HDLBits-22 Module add
Problem Statement
给定一个执行16位加法的模块add16。实例化两次来创建一个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 );

HDLBits刷题合集—4 Modules: Hierarchy_第6张图片
代码如下:

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
	wire cin,cout1,cout2;
    wire [15:0] sum1,sum2;
    
    assign cin=0;
    add16 add1 (.a(a[15:0]), .b(b[15:0]), .cin(cin), .sum(sum1), .cout(cout1));
    add16 add2 (a[31:16], b[31:16], cout1, sum2, cout2);
    assign sum = {sum2,sum1};
    
endmodule

HDLBits-23 Module fadd
Problem Statement
在本练习中,你将创建一个具有两个层次结构的电路。top_module将实例化2次add16(提供的),每个add16实例化16次add1(必须自己编写)。因此,必须编写两个模块:top_module和add1。

与上一题module_add一样,你将获得一个执行16位加法的add16模块。你必须实例化2次来创建一个32位加法器。一个add16模块计算加法结果的低16位,而第二个add16模块计算结果的高16位。设计的32位加法器不需要处理低位进位(假设为0)或向高位进位(忽略)。

所提供的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 );

回想一下,全加法器进位CO与和SUM计算a+b+cin。
综上所述,本次设计共有三个模块:
top_module — 顶层模块包括两个add16模块
add16, provided — 一个16位加法器包括16个一位加法器
add1 — 一个一位全加器模块

HDLBits刷题合集—4 Modules: Hierarchy_第7张图片
代码如下:

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
    wire cin1,cout1,cout2;
    wire [15:0] sum1,sum2;
    
    assign cin1=0;
    add16 add1 (a[15:0], b[15:0], cin1, sum1[15:0], cout1);
    add16 add2 (a[31:16], b[31:16], cout1, sum2[15:0], cout2);
    assign sum = {sum2, sum1};
    
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

HDLBits-24 Module cseladd
Problem Statement
行波进位加法器的一个缺点(参见前面的练习)是加法器计算执行的相当慢。第二级加法器在第一级加法器完成之前不能开始执行计算,这使得加法器变慢。一种改进是进位选择加法器,如下所示。第一级加法器和前面一样,但是我们复制了第二级加法器,一个假设进位为0,另一个假设进位为1,然后使用一个快速的2选1多路复用器来选择执行哪一个。

在本练习中,向你提供了与前一个练习相同的模块add16,它将两个16位数字与低位进位相加,并生成一个16位的和。必须使用自己的16位2选1多路复用器实例化三个add16模块来构建c进位选择加法器。

给定的add16模块是:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );

HDLBits刷题合集—4 Modules: Hierarchy_第8张图片
代码如下:

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

    wire cin,cin1,cin2,cout;
    wire [15:0] sum0, sum1, sum2,sum_h;
    
    assign cin  = 0;
    assign cin1 = 0;
    assign cin2 = 1;
    add16 add0 (a[15:0], b[15:0], cin, sum0[15:0], cout);
    add16 add1 (a[31:16], b[31:16], cin1, sum1[15:0],);
    add16 add2 (a[31:16], b[31:16], cin2, sum2[15:0],);
    
    always @(*) 
        begin
            case(cout)
                1'b0: sum_h = sum1;
                1'b1: sum_h = sum2;
            endcase
        end
        
    assign sum = {sum_h,sum0};
    
endmodule

HDLBits-25 Module addsub
Problem Statement
加法减法器可以利用加法器构建,方法是选择性地对其中一个输入求反,这等价于先对输入求反码,然后再加1。最终的结果是一个可以做两种操作(即加法和减法)的电路:(a + b + 0)和(a + ~b + 1)。

给定的add16模块是:
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] 与复制32次的sub异或),还要将sub连接到加法器的低位来的进位。

HDLBits刷题合集—4 Modules: Hierarchy_第9张图片
代码如下:

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

    wire [31:0] b_n;
    wire cout1,cout2;
    
    assign b_n = b ^ {32{sub}};
    add16 add0 (a[15:0], b_n[15:0], sub, sum[15:0], cout1);
    add16 add1 (a[31:16], b_n[31:16], cout1, sum[31:16], cout2);
    
endmodule

Note
新手一枚,主要分享博客,记录学习过程,后期参考大佬代码或思想会一一列出。欢迎大家批评指正!

你可能感兴趣的:(HDLBits刷题合集—4 Modules: Hierarchy)