0
点赞
收藏
分享

微信扫一扫

【Verilog刷题记录3】第二章第三节——层次结构

code_balance 2022-01-31 阅读 26

目录

模块

 按名称

按位置

D触发器

模块和矢量

加法器

全加器

同步加法器

减法器


定义连接线的时候,一定要注意位宽的问题,尤其是有矢量的情况下;在命名导线和模块实例时要小心:名称必须是唯一的;进行按位运算的时候,没有规定的情况两个操作数的位宽要相同

模块

模块的层次结构是通过实例化一个模块在另一个模块中创建的,只要使用的所有模块都属于同一个项目(因此编译器知道在哪里可以找到该模块)。

一个模块的代码不会写入另一个模块的主体(不同模块的代码不嵌套)。

题目:实例化模块a,并将模块a和顶层模块进行连接,其中mod_a的定义如下

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

 按名称

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

通过名称将信号连接到模块的端口,即使端口列表发生变化,电线也能保持正确连接。

mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );

按位置

module top_module ( input a, input b, output out );
mod_a mod_a_inst(a,b,out);
endmodule//要注意顺序

实例化模块时,端口根据模块的声明从左到右连接。例如:

mod_a instance1 ( wa, wb, wc );

如果模块的端口列表发生更改,则还需要查找和更改模块的所有实例化以匹配新模块。

D触发器

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

提供给您的模块是:module my_dff ( input clk, input d, output q );

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

 

module top_module ( input clk, input d, output q );
wire	dff12;	//定义12之间的线
wire	dff23;	//定义23之间的线
 
my_dff a
(
    .clk	    (clk)	,
    .d		    (d)		,
    .q			(dff12)
);

my_dff b
(
    .clk	(clk)	,
    .d		(dff12) ,		
    .q		(dff23)
);
    
my_dff c
(
    .clk	(clk)	,
    .d		(dff23) ,	
    .q		(q)	
);

endmodule

模块和矢量

模块端口不再是单个引脚,而是将矢量作为端口的模块,将向其附加线矢量而不是普通线路。

实例化三个模块并将它们连接起来,并写一个选择器,当sel为00时输出d,当sel为01时输出经过第一个触发器后的q值,以此类推。这里选择用case语句来实现。需要注意的是定义新的连接线时,要注意线位宽问题,如果没有定义则会给出警告

module top_module ( 
    input clk, 
    input [7:0] d, 
    input [1:0] sel, 
    output [7:0] q 
);
    wire    [7:0] dff12;	//定义12之间的连接线  
    wire	[7:0] dff23;	//定义23之间的连接线
    wire	[7:0] dff3m;	//定义3和选择器的连接线
 
my_dff8 a(.clk(clk), .d(d), .q(dff12));
my_dff8 b(.clk(clk), .d(dff12),.q(dff23));
my_dff8 c(.clk(clk), .d(dff23),.q(dff3m));

    always@(*)	
        case(sel)
            2'b00 :	q =	d;
            2'b01 :	q = dff12;
            2'b10 : q = dff23;
            2'b11 : q = dff3m;
        endcase

endmodule

官网提供的参考答案

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

	wire [7:0] o1, o2, o3;		// output of each my_dff8
	
	// Instantiate three my_dff8s
	my_dff8 d1 ( clk, d, o1 );
	my_dff8 d2 ( clk, o1, o2 );
	my_dff8 d3 ( clk, o2, o3 );

	// This is one way to make a 4-to-1 multiplexer
	always @(*)		// Combinational always block
		case(sel)
			2'h0: q = d;
			2'h1: q = o1;
			2'h2: q = o2;
			2'h3: q = o3;
		endcase

endmodule

加法器

提供的模块具有以下声明:add16

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

实例化两个加法器,加法器1对输入的低位进行运算,加法器2对输入的高位进行运算,将它们在内部进行连接,并将最后的结果赋值给顶层模块的sum 

全加器

此设计中有三个模块:

  • top_module— 您的顶级模块包含两个...
  • add16,提供 — 一个 16 位加法器模块,由 16 个...
  • add1— 一个 1 位全加法器模块。

 

 

/*我的解答*/
module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    
    wire	[0:0]	add12; //定义第一个加法器与第二个加法器的连接线
    wire	[15:0]	sum1;  //定义第一个加法器的输出线
    wire	[31:16]	sum2;  //定义第二个加法器的输出线
    add16 add16_inst1(
        .a(a[15:0])		,
        .b(b[15:0])		,
        .cout(add12)    ,
        .sum(sum1)	
    );
    add16 add16_inst2(
        .a(a[31:16])	,
        .b(b[31:16])	,
        .cin(add12)	    ,
        .sum(sum2)
    );
    assign sum   = {sum2,sum1}; 

endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );
    assign {cout,sum} = a + b + cin;
endmodule

同步加法器

提供的模块具有以下声明:add16

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

 

实例化三个加法器,然后根据图示进行连接,选择器用case语句完成 

module top_module(
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
);
    wire	[0:0]	sel  ; //定义一位的选择信号
    wire	[15:0]	sum1;  //定义第一个加法器的输出线
    wire	[31:16]	sum2;  //定义第二个加法器的输出线
    wire	[31:16]	sum3;  //定义第三个加法器的输出线

    add16 add16_inst1(
        .a(a[15:0])		,
        .b(b[15:0])		,
        .cout(sel)      ,
        .cin(1'b0)		,
        .sum(sum1)	
    );
    add16 add16_inst2(
        .a(a[31:16])	,
        .b(b[31:16])	,
        .cin(1'b0)	    ,
        .cout( )		,
        .sum(sum2)
    );
    add16 add16_inst3(
        .a(a[31:16])	,
        .b(b[31:16])	,
        .cout( )		,
        .cin(1'b1)		,
        .sum(sum3)		,
    );
 
    always@(*)
        case(sel)
            1'b0 : sum = {sum2,sum1}; 
            1'b1 : sum = {sum3,sum1};
        endcase

endmodule

减法器

提供了一个 16 位加法器模块

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

 

需要注意的是异或时位宽需要一样,也就是sub也需要是32位的,否则最后的结果是错误的,可以利用{}进行复制的操作

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    wire	[31:0] 	xor_wire; //定义经过xor门后的输出线   
    wire	[0:0]	add12; //定义第一个加法器与第二个加法器的连接线
    wire	[15:0]	sum1;  //定义第一个加法器的输出线
    wire	[31:16]	sum2;  //定义第二个加法器的输出线
 
    assign xor_wire = {32{sub}} ^ b;
 
    add16 add16_inst1(
        .a(a[15:0])			,
        .b(xor_wire[15:0])	,
        .cin(sub)			,
        .cout(add12)  		,
        .sum(sum1)	
    );
    add16 add16_inst2(
        .a(a[31:16])		,
        .b(xor_wire[31:16])	,
        .cin(add12)	   	    ,
        .cout( )			,
        .sum(sum2)
    );

    assign sum = {sum2,sum1};

endmodule
举报

相关推荐

0 条评论