HDLBits——Modules:Hierarchy

HDLBits——Modules:Hierarchy,第1张

HDLBits——Modules:Hierarchy HDLBits——Modules:Hierarchy Problem 19 : Modules Requirement:

创建一个下级模块 mod_a,将其的三个端口 in1 ,in2 ,out 按照图中的连接方式,分别连接到顶层模块的 a ,b,out 端口上。

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

    mod_a mod_a (
        .in1(a),
        .in2(b),
        .out(out)
    );
        
endmodule

PS:虽然不同的模块写在不同的 .v 文件中,但只要这些模块在开发软件中处于一个 Project。综合器就能在例化模块时,找到对应的模块和 .v 文件。模块中可以例化其他模块,但不允许再定义其他模块。

Timing Diagram:

Problem 20: Connecting ports by position(Module pos) Requirement:

给出了一个名为 mod_a 的模块,该模块按顺序具有 2 个输出和 4 个输入。将 6 个端口按位置顺序与顶层的端口 out1,out2,a,b,c 和 d 相连接。已知 module mod_a ( output, output, input, input, input, input );

Solution:
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

PS:对于给出的模块来说,不知道 mod_a 这个模块的端口名是什么,所以只能按照位置的顺序来连接,注意对应好输出输出。

Timing Diagram:

Problem 21: Connecting ports by name(Module name) Requirement:

给出了一个名为 mod_a 的模块,该模块按某种顺序具有 2 个输出和 4 个输入。将 6 个端口按名字与顶层的端口相连接。已知 module mod_a ( output out1, output out2, input in1, input in2, input in3, input in4);

Solution:
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
Timing Diagram:

Problem 22: Three modules(Module shift) Requirement:

给出了一个名为 my_dff 的模块,包含两个输入和一个输出(实现D触发器的功能)。实例化三个 my_dff,然后将它们连接在一起,构成长度为 3 的移位寄存器。已知:module my_dff ( input clk, input d, output q );

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

    wire w12,w23;
    my_dff d1 (
        .clk(clk),
        .d(d),
        .q(w12)
    );
    my_dff d2 (
        .clk(clk),
        .d(w12),
        .q(w23)
    );
    my_dff d3 (
        .clk(clk),
        .d(w23),
        .q(q)
    );

endmodule

PS:要在模块内部进行连接,需要先声明一些连线。

Timing Diagram:

Problem 23: Modules and vectors(Module shift8) Requirement:

本题给出了一个名为 my_dff8 的模块,包含两个输入和一个输出(实现一个 8bit 的 D 触发器)。请实例化三个,并将它们连接在一起,形成一个长度为 3 的 8bit 移位寄存器。此外,再写出一个 4 选 1 多路复用器(未提供模块模型),根据输入的 sel[1:0] 选择要输出的内容:输入 D 的值,在第一个 D 触发器之后的值,第二个或第三个 D 触发器之后的值(可以说 sel 选择的是输入延迟的的周期数,0~3 个时钟周期不等)。

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

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

    wire [7:0] w1,w2,w3;
    my_dff8 my_dff81 ( 
        .clk(clk), 
        .d(d), 
        .q(w1)
         );
    my_dff8 my_dff82 ( 
        .clk(clk), 
        .d(w1), 
        .q(w2)
         );
    my_dff8 my_dff83 ( 
        .clk(clk), 
        .d(w2), 
        .q(w3)
         );
    always @(*) begin
        case (sel)
        0: begin q <= d; end
        1: begin q <= w1; end
        2: begin q <= w2; end
        3: begin q <= w3; end
    endcase
    end
    

endmodule

PS:向量可以取代单根连接线作为模块的端口。正如 Verilog 的语法一样,端口的向量长度不必与连接到它的导线匹配,但这将导致向量的零填充或截断(高位填充,高位截断)。

注意:没有给出多路复用器,一种实现方法是在一个always块内使用case语句。必须在 always 块内才能使用 case 语句,否则报错。还有 case 中的 q 必须是 reg 型,不能是 wire 型,因为不能持续地赋值(assign),得有记忆性。

Why:case 语句属于行为级建模,必须用在过程块中,即 always 或者 initial 中的 begin…end 或者 fork…join 语句中,但是由于 initial 语句块一般只用于测试,不可综合,因此只考虑 always 语句块中使用 case 语句。

Timing Diagram:

Problem 24: Adder 1(Module add) Requirement:

给出了一个可以做 16bit 加法的模块 add16,实例化两个 add16 以达到 32bit 加法。一个 add16 模块计算结果的低 16 位,另一个 add16 模块在接收到第一个的进位后计算结果的高 16 位。此 32bit 加法器不需要处理输入进位(假设为0)和输出进位(无需进位),但为了结果的正确仍要处理进位信号。也就是 add16 模块执行 16bit 的 a+b+cin,而顶层模块执行 32bit 的 a+b。

已知 16 bit 的模块声明为:

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
);
    parameter z = 0;
    wire w;
    add16 add1 (
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(z),
        .sum(sum[15:0]),
        .cout(w)
    );
    add16 add2 (
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(w),
        .sum(sum[31:16])
    );

endmodule

PS:进位信号没有线网所连接就不用写了。

Timing Diagram:

Problem 25: Adder 2(Module fadd) Requirement:

在本题中,您将描述一个具有两级层次结构的电路。在 top_module 中,实例化两个 add16 模块,每个 add16 中实例化 16 个 add1 实例。与 Problem 24 一样,32 位加法器同样不需要处理进位输入(假设为0)和进位输出(无需进位)信号。

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

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

1、top_module:包含两个 16 位加法器的顶层模块;

2、add16(已给出):一个16bit的加法器,由16个全加器构成;

3、add(未给出):1bit全加器。

需要描述两个模块:top_module 和 add1。

小提示:全加器的逻辑表达式

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

    wire w;
    add16 add1 (
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(1'b0),
        .sum(sum[15:0]),
        .cout(w)
    );
    add16 add2 (
        .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


Timing Diagram:

Problem 26: Carry-select adder (Module cseladd) Requirement:

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

这次来实现一个改进型的加法器,第一级加法器保持不变,第二级加法器实现两个,一个假设进位为0,另一个假设进位为1。然后使用第一级结果和 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 reg [31:0] sum
);

    wire w;
    reg [15:0] s0,s1;
    add16 add1 (
        .a(a[15:0]),
        .b(b[15:0]),
        .cin(1'b0),
        .sum(sum[15:0]),
        .cout(w)
    );
    add16 add2 (
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(1'b0),
        .sum(s0)
    );
    add16 add3 (
        .a(a[31:16]),
        .b(b[31:16]),
        .cin(1'b1),
        .sum(s1)
    );
    always @(*) begin
        if (w == 0) begin
            sum[31:16] = s0;
        end
        else begin
            sum[31:16] = s1;
        end
    end

endmodule

改进:二选一直接用问号冒号语句就行,还能用 wire 类型。

assign sum[31:16] = w ? s1 : s0;

PS:这是选择进位加法器(CSA: Carry-Select Adder),相对于上一题的行波进位加法器(也叫逐级进位加法器,RCA: Ripple-Carry Adder)延迟小一半左右,但是比增多了50%的逻辑资源。

Timing Diagram:

Problem 27: Adder–subtractor (Module addsub) Requirement:

减法器可以由加法器来构建,对其中一个数取相反数(逐位取反加1)即可。

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

如下图所示构建加减法器,要求实例化两次 add16:

当 sub 为 1 时,使用 32 位的异或门对 b 进行取反(这也可以被视为 b[31:0] 与 sub 复制 32 次相异或),同时 sub 信号连接到加法器的进位。

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

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

endmodule

PS:异或门也可以看作是可编程的非门,其中一个输入控制输出为另一个输入或是其反。以下两个电路都是异或门:

Timing Diagram:


PS:还有好多题啊,俗话说的好,一口气吃不成一个胖子,继续加油哇!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5610017.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存