【HDLBits】Module合集(练习均用两种方法解决)
Module 命名方式-端口名称 vs 端口位置
端口位置 connecting by postion
通过位置去将wire连接到端口(常见)
在实例化一个模块时,端口根据模块位置的声明从左到右依次被连接
练习:Module pos
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a inst1 (out1,out2,a,b,c,d);
endmodule
端口名称 connecting by name
语法:.端口名(信号名)
即使端口顺序改变,通过名字连接信号和端口也是正确的。
实例化时顺序可以和定义的顺序不一致
练习:Module name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a inst (.out1(out1),.out2(out2),.in1(a),.in2(b),.in3(c),.in4(d));
endmodule
练习:Module shift
module top_module ( input clk, input d, output q );
//connecting by postion
wire q1,q2;
my_dff inst1(clk, d, q1);
my_dff inst2(clk, q1, q2);
my_dff inst3(clk, q2, q);
//connecting by name
// wire q1,q2;
// my_dff inst1(.d(d), .q(q1), .clk(clk)); //顺序不同也是对的
// my_dff inst2(.clk(clk), .d(q1), .q(q2));
// my_dff inst3(.clk(clk), .d(q2), .q(q));
endmodule
练习:Module shift8
This exercise is an extension of module_shift. Instead of module ports being only single pins, we now have modules with vectors as ports, to which you will attach wire vectors instead of plain wires. Like everywhere else in Verilog, the vector length of the port does not have to match the wire connecting to it, but this will cause zero-padding or trucation of the vector. This exercise does not use connections with mismatched vector lengths.
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. (Essentially, sel selects how many cycles to delay the input, from zero to three clock cycles.)
The module provided to you is: 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] q1, q2, q3;
//connecting by position
my_dff8 d1 ( clk, d, q1 );
my_dff8 d2 ( clk, q1, q2 );
my_dff8 d3 ( clk, q2, q3 );
//connecting by name
//my_dff8 d1(.clk(clk), .d(d), .q(q1) );
//my_dff8 d2 (.clk(clk), .d(q1), .q(q2) );
//my_dff8 d3 (.clk(clk), .d(q2), .q(q3) );
always @(*)
case(sel)
2'h0: q = d;
2'h1: q = q1;
2'h2: q = q2;
2'h3: q = q3;
endcase
endmodule
练习:Module add
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).
Connect the modules together as shown in the diagram below. The provided module add16 has the following declaration:
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
);
//connecting by name
wire out_in;
wire [15:0] sum1,sum2;
add16 inst1(.a(a[15:0]), .b(b[15:0]), .cin(1'b0), .cout(out_in), .sum(sum1));
add16 inst2(.a(a[31:16]), .b(b[31:16]), .cin(out_in), .sum(sum2));
assign sum = {sum2, sum1}; //sum2是高位,sum1是低位,千万不要写反
//connecting by position
// wire out_in, cout;
// wire [15:0] sum1,sum2;
// add16 inst1(a[15:0], b[15:0], 1'b0, sum1, out_in,);
// add16 inst2(a[31:16], b[31:16], out_in, sum2, cout);
// assign sum = {sum2, sum1};
endmodule
练习:Module fadd 两个层次结构的电路
本质上是在上一个练习的基础上加一个全加器模块。
(如果忘记全加器的知识,题干中间有我对这部分内容的补充)
In this exercise, 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.
Like module_add, you are given a module add16 that performs a 16-bit addition. You must 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. Your 32-bit adder does not need to handle carry-in (assume 0) or carry-out (ignored).
Connect the add16 modules together as shown in the diagram below. The provided module add16 has the following declaration:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
Within each add16, 16 full adders (module add1, not provided) are instantiated to actually perform the addition. You must write the full adder module that has the following declaration:
module add1 ( input a, input b, input cin, output sum, output cout );
Recall that a full adder computes the sum and carry-out of a+b+cin.
full adder全加器:
符号
全加器就是考虑进位的加法运算器。根据它的功能,可以列出它的真值表
输入端有CI,A,B
CI:前一次运算后是否有进位,有进位则为1,无进位则为0.
A:被加数
B:加数
输出端:S,CO
S:输出结果
CO:输出本次运算的进位
In summary, there are three modules in this design:
- top_module — Your top-level module that contains two of…
- add16, provided — A 16-bit adder module that is composed of 16 of…
- add1 — A 1-bit full adder module.
If your submission is missing a module add1, you will get an error message that says Error (12006): Node instance “user_fadd[0].a1” instantiates undefined entity “add1”.
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire out_in, cout;
wire [15:0] sum1,sum2;
add16 inst1(a[15:0], b[15:0], 1'b0, sum1, out_in,);
add16 inst2(a[31:16], b[31:16], out_in, sum2, cout);
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
练习:Module cseladd
One drawback of the ripple carry adder is that the delay for an adder to compute the carry out (from the carry-in, in the worst case) is fairly slow, and the second-stage adder cannot begin computing its carry-out until the first-stage adder has finished. This makes the adder slow.
ripple carry adder 进位传播加法器
ripple carry adder是由多个全加器(Full Adder)串联构成的,每个全加器负责计算两个二进制位的和,并考虑进位输入和进位输出。
ripple carry adder总延迟主要由两部分组成:
- 传播延迟:每个加法器(Full Adder)都有一个传播延迟。对于一个n位RCA,总的传播延迟是n个全加器的延迟。
2.进位延迟:每个进位输出需要传递到下一个加法器,整个进位传递过程是线性的。因此,ripple carry adder随着位宽的增加,延迟逐渐增大。
One improvement is a carry-select adder (进位选择加法器), shown below.
The first-stage adder is the same as before, but we duplicate the second-stage adder, one assuming carry-in=0 and one assuming carry-in=1, then using a fast 2-to-1 multiplexer to select which result happened to be correct.
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.
Connect the modules together as shown in the diagram below. The provided module add16 has the following declaration:
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;
wire [15:0] sum1,sum2;
wire [15:0] s1,s2;
add16 inst1(a[15:0], b[15:0], 1'b0, sum1, cout);
add16 inst2(a[31:16], b[31:16], 1'b0, s1);
add16 inst3(a[31:16], b[31:16], 1'b1, s2);
always @(*)begin
case(cout)
1'b0:sum={s1,sum1};
1'b1:sum={s2,sum1};
endcase
end
endmodule
练习:Module addsub(adder-subtractor)
An adder-subtractor can be built from an adder by optionally negating one of the inputs, which is equivalent to inverting the input then adding 1. The net result is a circuit that can do two operations: (a + b + 0) and (a + ~b + 1). See Wikipedia if you want a more detailed explanation of how this circuit works.
Build the adder-subtractor below.
You are provided with a 16-bit adder module, which you need to instantiate twice:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
Use a 32-bit wide XOR gate to invert the b input whenever sub is 1.
(This can also be viewed as b[31:0] XORed with sub replicated 32 times. See replication operator.). Also connect the sub input to the carry-in of the adder.
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire cout;
wire [15:0] sum1,sum2;
wire [31:0] m,n;
assign m = {32{sub}};
assign n = b^m;
add16 inst1(a[15:0], n[15:0], sub, sum1, cout);
add16 inst2(a[31:16], n[31:16], cout, sum2);
assign sum = {sum2,sum1};
endmodule