Verilog学习笔记HDLBits——Module:Hierarchy

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

到目前为止,您已经熟悉了模块,它是一种通过输入和输出端口与外部进行交互的电路。更大、更复杂的电路是由更小的模块和连接在一起的其他模块(如赋值语句和总是块)组成更大的模块来构建的。这就形成了一个层次结构,因为模块可以包含其他模块的实例。

一、Module:Hierarchy

1.Module

Practice: create one instance of module mod_a, then connect the module’s three pins (in1, in2, and out) to your top-level module’s three ports (wires a, b, and out). The module mod_a is provided for you — you must instantiate it.
翻译:根据下图,实例化一个下层模块mod_a,将其三个端口in1,in2,out按照图中的连接方式,分别连接到顶层模块的a,b,out端口上。mod_a模块已默认提供给你,不需要自己写,只需在顶层模块中例化它即可。模块的例化有两种方式:按端口位置和按端口名称

module mod_a ( input in, output out );		//定义了一个名为mod_a的模块
    ... // Module body
endmodule

module top_module ( input a, output out );	//定义了名为top_module的模块
	mod_a instance1 ( .in(a), .out(out));	//在top_module模块中例化mod_a模块
endmodule
//mod_a是被例化模块的模块名,instance1是实例名,()内是两个模块的端口信号的连接 

在这里插入图片描述

Solution(不唯一,仅供参考):

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

Timing Diagram

在这里插入图片描述

2.Connecting ports by position

Practice:You are given a module named mod_a that has 2 outputs and 4 inputs, in that order. You must connect the 6 ports by position to your top-level module’s ports out1, out2, a, b, c, and d, in that order.
翻译:得到一个名为mod_a的模块,它有2个输出和4个输入,按此顺序。按照下图的关系进行例化。
在这里插入图片描述

Solution(不唯一,仅供参考):

module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);	
    mod_a instance1(out1,out2,a,b,c,d);//注意输出和输入的顺序
endmodule

Timing Diagram

在这里插入图片描述

3.Connecting ports by name

Practice: You are given a module named mod_a that has 2 outputs and 4 inputs, in some order. You must connect the 6 ports by name to your top-level module’s ports:
翻译:你会得到一个名为mod_a的模块,它有2个输出和4个输入,按某种顺序。你必须按名称将这6个端口连接到你的顶级模块的端口.
提示:本题的例化方法与第一次例化方法相同,此方法在对应好每个端口后,可以不用考虑顺序问题,
在这里插入图片描述

Solution(不唯一,仅供参考):

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

endmodule

Timing Diagram
在这里插入图片描述

4.Three modules

Practice:You are given a module my_dff with two inputs and one output (that implements a D flip-flop). Instantiate three of them, then chain them together to make a shift register of length 3. The clk port needs to be connected to all instances…
翻译:给你一个模块my_dff,它有两个输入和一个输出(它实现了一个D触发器)。实例化其中三个,然后将它们链接在一起,形成长度为3的移位寄存器。如下图所示。
在这里插入图片描述

Solution(不唯一,仅供参考):

module top_module ( input clk, input d, output q );
wire q1,q2;
    my_dff my_dff1(clk,d,q1);
    my_dff my_dff2(clk,q1,q2);
    my_dff my_dff3(clk,q2,q);
endmodule

法二

module top_module ( input clk, input d, output q );
wire q1,q2;
    my_dff my_dff1(.clk(clk), .d(d), .q(q1));
    my_dff my_dff2(.clk(clk), .d(q1), .q(q2));
    my_dff my_dff3(.clk(clk), .d(q2), .q(q));
endmodule

Timing Diagram

在这里插入图片描述

5.Modules and vectors

Practice:You are given a module my_dff8 with two inputs and one output (that implements a set of 8 D flip-flops). Instantiate three of them, then chain them together to make a 8-bit wide shift register of length 3. In addition, create a 4-to-1 multiplexer (not provided) that chooses what to output depending on sel[1:0]: The value at the input d, after the first, after the second, or after the third D flip-flop.
翻译:给您一个模块my_dff8,它有两个输入和一个输出(它实现了一组8个D触发器)。实例化其中三个,然后将它们链接在一起,形成一个长度为3的8位宽移位寄存器。另外,创建一个4选1的多路选择器器(未提供),它根据sel[1:0]选择输出内容:输入d处的值,在第一个、第二个或第三个d触发器之后。
在这里插入图片描述

Solution(不唯一,仅供参考):

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'b00: q=d;
            2'b01: q=q1;
            2'b10: q=q2;
            2'b11: q=q3;
        endcase
    end

endmodule

Timing Diagram
在这里插入图片描述

6.Adder 1

Practice:You are given a module add16 that performs a 16-bit addition. Instantiate two of them to create a 32-bit adder. One add16 module computes the lower 16 bits of the addition result, while the second add16 module computes the upper 16 bits of the result, after receiving the carry-out from the first adder. Your 32-bit adder does not need to handle carry-in (assume 0) or carry-out (ignored), but the internal modules need to in order to function correctly. (In other words, the add16 module performs 16-bit a + b + cin, while your module performs 32-bit a + b).
翻译:给了一个实现16位加法器的模块add16,实例化两个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 );

在这里插入图片描述

Solution(不唯一,仅供参考):

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire cout1;
    add16 add1(.a(a[15:0]), 
               .b(b[15:0]), 
               .cin(1'b0), 
               .sum(sum[15:0]), 
               .cout(cout1));
    add16 add2(.a(a[31:16]), 
               .b(b[31:16]), 
               .cin(cout1), 
               .sum(sum[31:16]), 
               .cout());
endmodule

Timing Diagram
在这里插入图片描述

7.Adder 2

Practice:you will create a circuit with two levels of hierarchy. Your top_module will instantiate two copies of add16 (provided), each of which will instantiate 16 copies of add1 (which you must write). Thus, you must write two modules: top_module and add1.
翻译:你将创建一个有两个层次的电路。top_module将实例化add16的两个副本(提供),每个副本将实例化add1的16个副本(自己编写)。因此,必须编写两个模块:top_module和add1。
提示:add1需要自己编写,全加器的逻辑表达式 为sum = a ^ b ^ cin; cout = a&b | a&cin | b&cin;

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

在这里插入图片描述

Solution(不唯一,仅供参考):

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire cout1;
    add16 add_16(
                .a(a[15:0]),
                .b(b[15:0]),
                .cin(0),
                .sum(sum[15:0]),
                .cout(cout1)
    );
    add16 add_32(
                .a(a[31:16]),
                .b(b[31:16]),
       			 .cin(cout1),
                .sum(sum[31:16]),
                .cout()
    );

endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );
    assign {cout,sum} = a+b+cin;
    //或采用逻辑表达式
    //assign sum = a^b^cin;
    //assign cout = cout = a&b | a&cin | b&cin;
endmodule

Timing Diagram
在这里插入图片描述

8.Carry-aselect adder

Practice:In this exercise, you are provided with the same module add16 as the previous exercise, which adds two 16-bit numbers with carry-in and produces a carry-out and 16-bit sum. You must instantiate three of these to build the carry-select adder, using your own 16-bit 2-to-1 multiplexer.
翻译:在本练习中,为您提供与上一个练习相同的模块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 );

在这里插入图片描述
Solution(不唯一,仅供参考):

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire sel;
    wire [31:16] sum1,sum2;
    add16 add16_0(
                .a(a[15:0]),					
                .b(b[15:0]),
        		.cin(1'b0),
                .sum(sum[15:0]),
                .cout(sel)
);
     add16 add16_1(
                 .a(a[31:16]),					
                 .b(b[31:16]),
         		.cin(1'b0),
         		.sum(sum1[31:16]),
                .cout()
);
    add16 add16_2(
                .a(a[31:16]),					
                .b(b[31:16]),
        		.cin(1'b1),
                .sum(sum2[31:16]),
                .cout()
);
    assign sum[31:16] = sel?sum2:sum1;//也可以使用case语句
endmodule

Timing Diagram
在这里插入图片描述

8.Adder-subtractor

Practice:Build the adder-subtractor below.
翻译:构建下面的加-减法器。如图所示
**提示:**加-减法器可以由加法器构建,可选地对其中一个输入取反,这相当于将输入取反,然后加1。最终的结果是一个可以进行(a + b + 0)和(a + ~b + 1)两种操作的电路。

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

在这里插入图片描述
出错 assign bb = b^sub;
改进 assign bb = b^{32{sub}};
Solution(不唯一,仅供参考):

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

endmodule

Timing Diagram
在这里插入图片描述

总结

1、 在顶层模块中实例化(简称例化)下层模块时,只需关注下层模块的端口,而不必在乎它的内部代码。模块的层次化结构通过在一个模块中例化另一个模块来实现,只要这些模块都处于一个project(项目)中,编译器就能找到相对应的模块。注意,在一个模块中可以例化,但不允许定义和编写其他模块。
2、数字IC有自顶向下自底向上两种设计方法。前者先定义顶层功能块,再对其分析并不断分解成一个个子模块,直至无法进一步分解的底层功能块;后者先分析现有的功能块,然后用它们搭建更大规模的模块,直至顶层功能块。Verilog就用module(模块)来表示这一个个的功能块(具有特定功能的一块块电路),它可大可小,大到一个微处理器,小到一个晶体管,原则上都可作为一个模块。
3、always @()其中括号内加星号就是表示模块中所有的向量,也可以写为
always @(clk or d or sel or q)
4、全加器的逻辑表达式 为sum = a ^ b ^ cin; cout = a&b | a&cin | b&cin;sum表示和,cout表示进位。
5、6 7题实现的是行波进位加法器(也称串行进位或逐位进位加法器),这类加法器的缺点是较高位的相加结果必须等到低一位的进位产生之后才能开始计算,这使得加法器的计算延迟变大。选择进位是一种改进方法,如图所示,第一级加法器与之前相同,但第二级加法器有两个,一个假设进位为0,另一个假设进位为1,然后用2选1多路选择器来选择哪个是正确的。
6、例化的方法有两种

my_dff my_dff1(.clk(clk), .d(d), .q(q1));
my_dff my_dff1( clk, d, q);//按序排列

最好使用第一种方法,不容易出错

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA(Field-Programmable Gate Array)是一种可编程逻辑器件,它能够在电路中实现各种数字逻辑功能。Verilog语言则是一种硬件描述语言,用于描述数字系统的行为和结构。本文将通过基于Altera EP4CE10(一款FPGA芯片)进行的FPGA Verilog开发实战指南,向读者介绍如何使用Verilog语言开发FPGA应用。 首先,选择合适的开发工具,例如Altera Quartus Prime软件。在Quartus中,创建一个新的工程,并添加Verilog源文件,用于编写FPGA应用的逻辑代码。在编写代码时,需要了解基本的Verilog语法和模块化设计的原则。 接下来,将FPGA芯片选项设置为Altera EP4CE10,并进行引脚分配。引脚分配是将逻辑信号与FPGA芯片引脚相连接的过程。确保正确地将输入和输出信号与特定引脚相连接,以实现所需的功能。 然后,进行逻辑编译和映射。逻辑编译将Verilog代码转换为低级逻辑网表,并进行逻辑优化。映射阶段将逻辑网表映射到FPGA芯片中的逻辑单元和开关资源。 在映射之后,进行时序分析和布线。时序分析用于验证设计在时序要求下的正确性,以确保信号传输的稳定性和准确性。布线是将逻辑资源与FPGA芯片中的物理资源相互连接的过程。 最后,进行编程和调试。将生成的比特流文件下载到FPGA芯片中,并进行信号调试和性能优化。通过使用逻辑分析仪等工具,可以检查信号的波形和逻辑的正确性,并根据需要进行调整和改进。 在进行FPGA Verilog开发实战时,需要具备较好的数字电路基础和Verilog语言掌握程度。通过实践和经验积累,不断提升对FPGA开发的理解和技能,才能开发出高效和可靠的FPGA应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值