HDLBits学习------Problem 19~27

参考链接:HDLBits导学


Problem 19 : Modules

        问题:在顶层模块中例化下面的模块

       思路:例化有两种方式

按端口顺序mod_a instance1 ( wa, wb, wc );根据原模块的端口顺序例化(端口列表发生变化后修改很麻烦)

按端口名称mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) ); 直接对应端口名称进行例化

        解决:

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

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

endmodule

Problem 20: Connecting ports by position(Module pos)

        问题:按端口顺序例化下图模块

        解决: 

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

mod_a mod_a_inst(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 mod_a_inst(
	.out1(out1),
	.out2(out2),
	.in1(a),
	.in2(b),
	.in3(c),
	.in4(d)
);

endmodule

        注意:例化端口名和顶层模块名别搞反了


Problem 22: Three modules(Module shift)

        问题:实例化三个my_dff,然后将它们连接在一起,构成长度为3的移位寄存器。注意:clk端口需要连接到所有的寄存器实例上

        思路:从图中可以看出第二个my_dff的输入端口是第一个my_dff的输入端口,顶层模块的输入输出没有连接它们,所以它们之间需要定义一根线来连接,第二个到第三个同理

        解决:

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

wire d2,d3;

my_dff my_dff_inst1(
	.clk(clk),
	.d(d),
	.q(d2)
);

my_dff my_dff_inst2(
	.clk(clk),
	.d(d2),
	.q(d3)
);

my_dff my_dff_inst3(
	.clk(clk),
	.d(d3),
	.q(q)
);

endmodule

Problem 23: Modules and vectors(Module shift8)

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

        思路:相比于上一道题增加了一个四选一的选择器,使用always完成 

        解决:

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 my_dff_inst1(
	.clk(clk),
	.d(d),
	.q(q1)
);

my_dff8 my_dff_inst2(
	.clk(clk),
	.d(q1),
	.q(q2)
);

my_dff8 my_dff_inst3(
	.clk(clk),
	.d(q2),
	.q(q3)
);

always @(*) begin
	case(sel)
		2'b00:q = d;
		2'b01:q = q1;
		2'b10:q = q2;
		2'b11:q = q3;
	endcase
end
	
endmodule

        注意:此时wire的位宽为8位


Problem 24: Adder 1(Module add)

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

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 cout1;
wire[15:0] sum1,sum2;

add16 add16_inst1(
	.a(a[15:0]),
	.b(b[15:0]),
	.cin(0),
	.sum(sum1),
	.cout(cout1)
);

add16 add16_inst2(
	.a(a[31:16]),
	.b(b[31:16]),
	.cin(cout1),
	.sum(sum2),
);

assign sum = {sum2,sum1};

endmodule

Problem 25: Adder 2(Module fadd)

        问题:在本题中,您将描述一个具有两级层次结构的电路。在top_module中,实例化两个add16模块(已为您提供),每个add16中实例化16个add1实例(此模块需要您编写)。所以,您需要描述两个模块:top_module和add1

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

        思路:这个题和上一个题是类似的,add_16模块已经定义好了,但是需要自己实现add_1的全加器,从来实现add_16

借用大佬的写法,我只会++++

assign sum = a^b^cin;
assign cout = (a&b)|(a&cin)|(b&cin);

        解决:

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

wire cout1;
wire[15:0] sum1,sum2;

add16 add16_inst1(
	.a(a[15:0]),
	.b(b[15:0]),
	.cin(0),
	.sum(sum1),
	.cout(cout1)
);

add16 add16_inst2(
	.a(a[31:16]),
	.b(b[31:16]),
	.cin(cout1),
	.sum(sum2),
);

assign sum = {sum2,sum1};

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)

       概述:上一个练习中(Problem 25: Adder 2(Module fadd))实现的加法器应该叫做行波进位加法器(RCA: Ripple-Carry Adder)。这种加法器的缺点是计算进位输出的延迟是相当慢的(最坏的情况下,来自于进位输入)。并且如果前一级加法器计算完成之前,后一级加法器不能开始计算。这又使得加法器的计算延迟变大。

        问题:这次来实现一个改进型的加法器,如下图所示。第一级加法器保持不变,第二级加法器实现两个,一个假设进位为0,另一个假设进位为1。然后使用第一级结果和2选一选择器来选择哪一个结果是正确的。

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

         思路:高位加法器定义两个,一个的进位为1,另一个的进位为0,然后由低位加法器的进位来选择最后哪一个加法器输出

         解决:

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

wire cout1;
wire[15:0] sum1,sum2_1,sum2_2;

add16 add16_inst1(
	.a(a[15:0]),
	.b(b[15:0]),
	.cin(0),
	.sum(sum1),
	.cout(cout1)
);

add16 add16_inst2_1(
	.a(a[31:16]),
	.b(b[31:16]),
	.cin(0),
	.sum(sum2_1),
);

add16 add16_inst2_2(
	.a(a[31:16]),
	.b(b[31:16]),
	.cin(1),
	.sum(sum2_2),
);

assign sum = cout1?{sum2_2,sum1}:{sum2_1,sum1};

endmodule

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 );

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

        思路:sub重复32次的写法,sum分开进行输出,不使用拼接

        解决:

module top_module(
    input [31:0] a,
    input [31:0] b,
    input sub,
    output [31:0] sum
);
    
wire carry;
wire[31:0] b_nb = b^{32{sub}};

add16 add16_inst1(
	.a(a[15:0]),
	.b(b_nb[15:0]),
	.cin(sub),
    .sum(sum[15:0]),
	.cout(carry)
);

add16 add16_inst2(
	.a(a[31:16]),
	.b(b_nb[31:16]),
	.cin(carry),
    .sum(sum[31:16]),
);

endmodule

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值