HDLBits——Modules:Hierarchy

目录

  • HDLBits——Modules:Hierarchy
  • 问题19 Module
  • 将信息连接到端口
  • By position
  • By name
  • 问题20 Connecting ports by position(Module pos)
  • 问题21 Connecting ports by name(Module name)
  • 问题22 Three modules(Module shift)
  • 问题23 Modules and vectors(Module shift8)
  • 问题24 Adder 1(Module add)
  • 问题25 Adder 2(Module fadd)
  • 问题26 Carry-select adder (Module cseladd)
  • 问题27 Adder–subtractor (Module addsub)
  • 结语

问题19 Module

下图显示了一个带有子模块的简单的电路。在本练习中,创建模块 mod_a 的一个实例,然后将模块的三个引脚(in1、in2 和 out)连接到顶层模块的三个端口(线 a、b 和 out)。模块 mod_a 是为您提供的——您必须实例化它。

HDLBits(1)——Modules:Hierarchy_实例化

将信息连接到端口

将物理电线连接到端口有两种常用的方法: by position or by name. 按位置或按名称。

By position

按位置将电线连接到端口的语法应该很熟悉,因为它使用类似 C 的语法。实例化模块时,端口根据模块的声明从左到右连接。例如:

mod_a instance1 (wa,wb,wc);

这会实例化一个 mod_a 类型的模块,并给它一个实例名称“instance1”,然后将信号 wa(在新模块外部)连接到新模块的第一个端口(in1),将 wb 连接到第二个端口(in2),然后wc 到第三个端口(out)。

By name

按名称将信号连接到模块的端口可以使电线保持正确连接,即使端口列表发生更改。然而,这种语法更加冗长。

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 );
 
    mod_a instance2 (.out(out),
                     .in1(a),
                     .in2(b)
                    );

endmodule

问题20 Connecting ports by position(Module pos)

这个问题和上一个问题19类似。您将获得一个名为 mod_a 的模块,该模块按顺序具有 2 个输出和 4 个输入。您必须按位置将 6 个端口按顺序连接到顶层模块的端口 out1out2abcd

您将获得以下模块:

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

HDLBits(1)——Modules:Hierarchy_ci_02

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

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

endmodule

HDLBits(1)——Modules:Hierarchy_加法器_03

问题21 Connecting ports by name(Module name)

您将获得一个名为 mod_a 的模块,该模块按某种顺序具有 2 个输出和 4 个输入。您必须按名称将 6 个端口连接到顶层模块的端口:

HDLBits(1)——Modules:Hierarchy_ci_04


您将获得以下模块:

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

HDLBits(1)——Modules:Hierarchy_实例化_05

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

HDLBits(1)——Modules:Hierarchy_加法器_06

问题22 Three modules(Module shift)

您将获得一个带有两个输入和一个输出的模块 my_dff(实现 D 触发器)。将其中三个实例化,然后将它们链接在一起以制成长度为 3 的移位寄存器。 clk 端口需要连接到所有实例。

提供给你的模块是:

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

请注意,要建立内部连接,您需要声明一些连线。命名你的连线和模块实例时要小心:名称必须是唯一的。

HDLBits(1)——Modules:Hierarchy_加法器_07

module top_module ( input clk, input d, output q );
    
    wire w1_2;
    wire w2_3;
    
    my_dff dff1(
        .clk(clk),   
        .d(d),
        .q(w1_2)
    );
    
    my_dff dff2(
        .clk(clk),
        .d(w1_2),
        .q(w2_3)
    );
    
    my_dff dff3(
        .clk(clk),
        .d(w2_3),
        .q(q)
    );

endmodule

HDLBits(1)——Modules:Hierarchy_实例化_08

问题23 Modules and vectors(Module shift8)

本练习是 module_shift 的扩展。模块端口不再只是单个引脚,我们现在有带有向量作为端口的模块,您将连接线向量而不是普通线。与 Verilog 中的其他任何地方一样,端口的向量长度不必与连接到它的导线相匹配,但这会导致向量的零填充或截断。本练习不使用向量长度不匹配的连接。

您将获得一个带有两个输入和一个输出的模块 my_dff8(实现一组 8D 触发器)。实例化其中三个,然后将它们链接在一起,形成一个长度为38位宽移位寄存器。此外,创建一个41多路复用器(未提供),该多路复用器根据sel[1:0]:输入d处、第一个d触发器之后、第二个d触发器之后或第三个d触发器之后的值来选择要输出的内容。(本质上,sel选择延迟输入的周期数,从零到三个时钟周期。)

提供给你的模块是:

module my_dff8(input clk, input [7:0] d, output [7:0] q);

未提供多路复用器。一种可能的编写方法是在一个带有 case 语句的 always 块中。 (另见:mux9to1v)

HDLBits(1)——Modules:Hierarchy_实例化_09

module top_module ( 
    input clk,             //clock signal
    input [7:0] d,         //Enter 8 groups of data
    input [1:0] sel,       //2-bit selector
    output [7:0] q         //8-bit output
);
    wire [7:0] w1_1,w1_2,w1_3;   //8-bit output
    
    my_dff8 my_dff81(
        .clk(clk),
        .d(d),
        .q(w1_1)
    );
    
    my_dff8 my_dff82(
        .clk(clk),
        .d(w1_1),
        .q(w1_2)
    );
    
    my_dff8 my_dff83(
        .clk(clk),
        .d(w1_2),
        .q(w1_3)
    );
    
    always @(*) begin
        case(sel)
            0: begin q <= d; end
            1: begin q <= w1_1; end
            2: begin q <= w1_2; end
            3: begin q <= w1_3; end
    endcase
    end
       
    
endmodule

HDLBits(1)——Modules:Hierarchy_加法器_10

问题24 Adder 1(Module add)

您将获得一个执行16位加法的模块add16。实例化其中两个以创建32位加法器。一个add16模块计算加法结果的低16位,而第二个add16模块在从第一个加法器接收进位后计算结果的高16位。您的32位加法器不需要处理进位(假设为0)或进位(忽略),但内部模块需要处理才能正常工作。(换句话说,add16模块执行16a+b+cin,而您的模块执行32a+b)。

如下图所示将模块连接在一起。提供的模块 add16 具有以下声明:

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

![在这里插入图片描述](https://img-blog.csdnimg.cn/a3998a0a74924f95b124ef6d2e63c827.png

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    parameter z = 0;
    wire w;
    
    add16 add161(
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(z),
        .cout(w),
        .sum(sum[15:0])
    );

    add16 add162(
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(w),
        .sum(sum[31:16])
    );

endmodule

HDLBits(1)——Modules:Hierarchy_加法器_11

问题25 Adder 2(Module fadd)

在本练习中,您将创建具有两个层次结构的电路。您的 top_module 将实例化 add16 的两个副本(已提供),每个副本将实例化 add1 的 16 个副本(您必须编写)。

与module\u add一样,您也会得到一个执行16位加法的module 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 );

HDLBits(1)——Modules:Hierarchy_fpga开发_12


HDLBits(1)——Modules:Hierarchy_fpga开发_13

总之,本题中一共有三个模块:

  1. top_module:包含两个 16 位加法器的顶层模块;
  2. add16(已给出):一个16bit的加法器,由16个全加器构成;
  3. add(未给出):1bit全加器。

HDLBits(1)——Modules:Hierarchy_实例化_14

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
    
    wire w;
    
    add16 add161(
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(1'b0),
        .cout(w),
        .sum(sum[15:0])
    );

    add16 add162(
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(w),
        .sum(sum[31:16])
    );
    
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);

endmodule

HDLBits(1)——Modules:Hierarchy_实例化_15

问题26 Carry-select adder (Module cseladd)

问题25 实现的加法器叫做行波进位加法器(RCA: Ripple-Carry Adder),缺点是计算进位输出的延迟是相当慢的(最坏的情况下,来自于进位输入),前一级加法器计算完成之前,后一级加法器不能开始计算,使得加法器的计算延迟变大。

在本练习中,为您提供与前一练习相同的模块 add16,它将两个 16 位数字与进位相加,并产生一个进位和 16 位和。您必须使用您自己的 162 对 1 多路复用器来实例化其中的三个以构建进位选择加法器。

如下图所示将模块连接在一起。提供的模块 add16 具有以下声明:

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

HDLBits(1)——Modules:Hierarchy_fpga开发_16

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    
    wire [15:0] sum1;
    wire [15:0] sum2;
    wire [15:0] sum3;
    wire        cout;

    assign sum = cout ? {sum3, sum1} : {sum2, sum1};
        
    add16 add161(
        .a		(a[15:0]	),
        .b		(b[15:0]	),
        .sum	(sum1		),
        .cin	(1'b0		),
        .cout	(cout		)
    );
    
    add16 add162(
        .a		(a[31:16]	),
        .b		(b[31:16]	),
        .sum	(sum2		),
        .cin	(1'b0		),
        .cout	(			)
    );
    
    add16 add163(
        .a		(a[31:16]	),
        .b		(b[31:16]	),
        .sum	(sum3		),
        .cin	(1'b1		),
        .cout	(			)
    );


endmodule

HDLBits(1)——Modules:Hierarchy_ci_17

问题27 Adder–subtractor (Module addsub)

减法器可以由加法器来构建,对其中一个数取相反数(逐位取反加1)即可。最终结果是一个可以执行两种操作的电路:(a + b + 0)(a + ~b + 1)。如果您想更详细地了解该电路的工作原理,请参阅 Wikipedia。

为您提供了一个 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]sub 复制 32 次相异或),同时 sub 信号连接到加法器的进位。

HDLBits(1)——Modules:Hierarchy_ci_18

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire cout;
    wire [31:0] b_com;
    
    assign b_com = {32{sub}}^ b;  
    
    add16 add161(
        .a		(a[15:0]		),
        .b		(b_com[15:0]	),
        .cin	(sub			),
        .cout	(cout			),
        .sum	(sum[15:0]		)
    );
    
    add16 add162(
        .a		(a[31:16]		),
        .b		(b_com[31:16]	),
        .cin	(cout			),
        .cout	(				),
        .sum	(sum[31:16]		)
    );

endmodule

HDLBits(1)——Modules:Hierarchy_ci_19

结语

注意巩固练习