其他分享
首页 > 其他分享> > verilog language-module hierarchy

verilog language-module hierarchy

作者:互联网

Problem 19:Module

注意到程序开头都是 module,意味着我们写的程序都是一个模块电路

模块与模块之间构成了层级。

模块例化的基本语法:

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

顶层模块的下层模块 mod_a 相当于一个黑盒子,里面什么东西并不重要,重要的是输入输出端口。

模块信号连接的两种方式

  1. 按端口顺序

    mod_a instance1(wa,wb,wc);//模块名 实例名(定义连接 port 的信号
    //wa,wb,wc分别连接到模块的第一个端口(in1),第二个端口(in2),第三个端口(out)。
    

    这里的端口顺序指的是模块端口的定义顺序,一旦端口列表顺序发生改变,所有模块中的实例化中的端口都需要改变

  2. 按端口名称连接端口

    mod_a instance1(.out(wc),.in1(wa),.in2(wb));//根据端口名称指定外部信号的连接,和端口定义的顺序完全没有关系
    
module top_module ( input a, input b, output out );
        mod_a U_mod_a(
          .in1(a)
        , .in2(b)
        , .out(out));
    //mod_a U_mod_a(a, .b, out); //使用按照端口顺序的方式 声明信号连接
endmodule

Problem 20: Connecting ports by position(Module pos)

给出一个 4 输入,2 输出的 mod_a 模块、

给出的模块如下:

module mod_a ( output, output, input, input, input, input );//只标注输入输出端口而没有名字是不规范的,应该要赋予每个端口一个名字
module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);

    mod_a name(out1,out2,a,b,c,d);//这里题目并没有给出输入输出端口的名字,所以只能按照顺序来连接
  
endmodule

Problem 21:Connecting ports by name(Module name)

给出的模块如下:

module mod_a ( output out1, output out2, input in1, input in2, input in3, input in4);//这里给出了每个端口的名称
module top_module ( 
    input a, 
    input b, 
    input c,
    input d,
    output out1,
    output out2
);

    mod_a name(
        .out1(out1),
        .out2(out2),
        .in1(a),
        .in2(b),
        .in3(c),
        .in4(d));//这里按照模块端口名称进行连接,可以不用按顺序
endmodule

但如果按题目给出的顺序写成如下,会报错:

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

(猜测是因为题目给的模块顺序发生的改变,不知道内部什么结构,所以有点难调)

Problem 22:Three modules(Module shift)

给出一个名为 my_dff 的模块,包含两个输入和一个输出

module my_dff ( input clk, input d, output q );
module top_module ( input clk, input d, output q );
    wire m,n;
    my_dff name1(.clk(clk),.d(d),.q(m));//对my_dff进行了三次实例化,用了三个不同的名字(name1,name2,name3)
  
    my_dff name2(.clk(clk),.d(m),.q(n));//端口用了名称定义的方式,建议少用顺序定义的方式
    my_dff name3(.clk(clk),.d(n),.q(q));
endmodule

Problem 23:Module and vectors(Module shift8)

向量可以代替单根连接线作为模块的端口,在连接的时候也是向量连接,而不是单根导线

当端口的向量长度和连接的导线不匹配时,会导致向量的零填充或截断,

给出一个模块,包含两个输入和一个输出,实现一个 8bit 的 D 触发器。实例化三个模块,并连接在一起,形成一个长度为 3 的 8bit 的移位寄存器。

再加入一个 4 选 1 多路复用器,根据输入的 sel[1:0]选择要输出的内容:输入 D 的值,第一个 D 触发器之后的值……相当于是选择输入延迟的周期数,0~3 个时钟周期不等

给出:

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

实现:

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

	wire [7:0] o1, o2, o3;		// 声明每一个触发器的输出

	// Instantiate three my_dff8s
	my_dff8 d1 ( clk, d, o1 );
	my_dff8 d2 ( clk, o1, o2 );
	my_dff8 d3 ( clk, o2, o3 );

	// 这是实现4选1选择器的一种方法
	always @(*)		// 组合逻辑always块
		case(sel)
			2'h0: q = d;
			2'h1: q = o1;
			2'h2: q = o2;
			2'h3: q = o3;
		endcase

endmodule

Problem 24:Adder 1 (Module add)

给出一个 16bit 加法器模块 add16,实例化两个 add16 以达到 32bit 加法器。

原理:一个 add16 模块计算结果的低 16 位,另一个 add16 模块接受第一个的进位后计算结果的高 16 位。

给出:

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

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

Problem 25:Adder 2(Module fadd)

描述一个具有两级层次结构的电路,实例化两个 add16 模块,每个 add16 中实例化 16 个 add1 实例。

给出:

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

在每个 add16 中,实例化了 16 个全加器去执行加法操作,需要自己编写并声明。

全加器的逻辑表达式

实现

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);//
wire carry;
    add16 a1(.a(a[15:0])
             ,.b(b[15:0])
             ,.cin(0)
             ,.sum(sum[15:0])
             ,.cout(carry)
            );
    add16 a2(.a(a[31:16])
             ,.b(b[31:16])
             ,.cin(carry)
             ,.sum(sum[31:16])
             ,.cout()
    );
endmodule

module add1 ( input a, input b, input cin,output sum, output cout );

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

Problem 26:Carry-select adder(Module cseladd)

上面一个实现的加法器叫做行波进位加法器(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 );

实现:

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire carry;
    wire [31:16] sum0,sum1;
    add16 c1(.a(a[15:0])
             ,.b(b[15:0])
             ,.cin(0)
             ,.sum(sum[15:0])
             ,.cout(carry)
            );
    add16 c2(.a(a[31:16])
             ,.b(b[31:16])
             ,.cin(0)
             ,.sum(sum0[31:16])
             ,.cout());
   
    add16 c3(.a(a[31:16])
             ,.b(b[31:16])
             ,.cin(1)
             ,.sum(sum1[31:16])
             ,.cout());
            
    assign sum[31:16]=carry?sum1:sum0;
endmodule

以上是进位加法器(CSA:Carry-Select Adder),对比上一题的行波进位,加法器延迟小一半,但增多了 50% 的逻辑资源。

Problem 27:Adder–subtractor (Module addsub)

加减法器可以通过加法器去实现,对其中一个数取相反数(对输入数据取反,然后加 1)。

最终结果是一个可以执行以下两个操作的电路:a+b+0 和 a+~ b+1

给出 16bit 加法器模块:

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

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire carry;
    wire [31:0]b1;
    assign b1=b^{32{sub}};//当sub=1时,使用32位的异或门对B进行取反
    add16 c1(.a(a[15:0])
              ,.b(b1[15:0])
           ,.cin(sub)
           ,.sum(sum[15:0])
           ,.cout(carry)
          );
    add16 c2(.a(a[31:16])
             ,.b(b1[31:16])
             ,.cin(carry)
             ,.sum(sum[31:16])
             ,.cout()
            );
endmodule

标签:15,hierarchy,31,module,verilog,output,input,sum
来源: https://www.cnblogs.com/zjj666/p/15614833.html