-
概述
电路设计中通过module进行实例化设计来组合成更复杂的电路,连接module时,只要知道module的端口即可,无须关注内部实现。关于连接信号到module有两种方式:端口名称或端口位置。
- 按位置连线:根据module端口的定义顺序进行端口连接;例如:mod_a instance1(a, b, out);
- 按名称连线:根据模块名进行连接。例如:mod_a instance2(.out(out), .in1(a), .in2(b)); 实际项目中推荐使用该方法。
-
原理图+代码+仿真截图
- Modules
//Modules
module top_module ( input a, input b, output out );
mod_a instance1(.in1(a), .in2(b), .out(out)); //by name
// mod_a instance2(a, b, out); //by position
endmodule
- Module pos
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a instance1(out1, out2, a, b, c, d); // by position
endmodule
Module Name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a instance1(.in1(a), .in2(b), .in3(c), .in4(d), .out1(out1), .out2(out2)); // by name
endmodule
- Module shift
module top_module ( input clk, input d, output q );
wire q1,q2;
my_dff int1(.clk(clk), .d(d), .q(q1));
my_dff int2(.clk(clk), .d(q1), .q(q2));
my_dff int3(.clk(clk), .d(q2), .q(q));
endmodule
- Module shift8
module top_module (
input clk,
input [7:0] d,
input [1:0] sel,
output [7:0] q
);
wire [7:0] q1, q2, q3, q4;
my_dff8 inst1(.clk(clk), .d(d), .q(q1));
my_dff8 inst2(.clk(clk), .d(q1), .q(q2));
my_dff8 inst3(.clk(clk), .d(q2), .q(q3));
always @(sel)
begin
case(sel)
0: q4 = d;
1: q4 = q1;
2: q4 = q2;
3: q4 = q3;
endcase
end
assign q = q4;
endmodule
- Module add
使用两个16位的加法器,组成一个32位的加法器。
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire low_cout, high_cout;
wire [15:0] low_sum, high_sum;
add16 low(.a(a[15:0]), .b(b[15:0]), .cin(0), .sum(low_sum), .cout(low_cout)); // create low 16bits adder
add16 high(.a(a[31:16]), .b(b[31:16]), .cin(low_cout), .sum(high_sum), .cout(high_cout));// create high 16bits adder
assign sum = {high_sum, low_sum};
endmodule
- Module fadd
加法器是数字设计中最重要的基本模块,开始这道题目实现错误了,原因是因为add1模块的sum和cout的书写顺序错误导致的( assign {cout, sum} = a + b + cin),应该先写进位,后写和
另外这种加法器的缺点就是时间效率太差,后一位加法器,必须等待前一位加法器的进位。
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire cout_low, cout_high;
add16 low16(
.a(a[15:0]),
.b(b[16:0]),
.cin(0),
.sum(sum[15:0]),
.cout(cout_low)
);
add16 high16(
.a(a[31:16]),
.b(b[31:16]),
.cin(cout_low),
.sum(sum[31:16]),
.cout(cout_high)
);
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
// Full adder module here
assign {cout, sum} = a + b + cin;
endmodule
- Module cseladd
为了克服前一个加法器的时间效率的问题,这个就是改进版的题目。
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cout_low;
wire [15:0] sum1, sum2;
add16 low16(
.a(a[15:0]),
.b(b[15:0]),
.cin(0),
.cout(cout_low),
.sum(sum[15:0])
);
add16 high16_1(
.a(a[31:16]),
.b(b[31:16]),
.cin(0),
.cout(),
.sum(sum1)
);
add16 high16_2(
.a(a[31:16]),
.b(b[31:16]),
.cin(1),
.cout(),
.sum(sum2)
);
assign sum[31:16] = (cout_low == 1) ? sum2 : sum1;
endmodule
- Module addsub
练习了加法器,那减法器就是加上一个负数来实现,负数的补码表示原码取反加1。电路原理图如下:
另外,xor异或实现取反的操作。根据电路图实现代码。
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire cout_low;
wire [31:0] b_cin;
add16 low(
.a(a[15:0]),
.b(b_cin[15:0]),
.cin(sub),
.cout(cout_low),
.sum(sum[15:0])
);
add16 hight(
.a(a[31:16]),
.b(b_cin[31:16]),
.cin(cout_low),
.cout(),
.sum(sum[31:16])
);
assign b_cin = b ^ {32{sub}};
endmodule
-
总结
本节刷题,目的是使用module模块时按名称连线,这样代码代码可读性较强,即使端口列表顺序变化了。