目录
1、Modules
Connecting Signals to Module Ports
There are two commonly-used methods to connect a wire to a port: by position or by name.
By position
The syntax to connect wires to ports by position should be familiar, as it uses a C-like syntax. When instantiating a module, ports are connected left to right according to the module’s declaration. For example:
mod_a instance1 ( wa, wb, wc );
This instantiates a module of type mod_a and gives it an instance name of “instance1”, then connects signal wa (outside the new module) to the first port (in1) of the new module, wb to the second port (in2), and wc to the third port (out). One drawback of this syntax is that if the module’s port list changes, all instantiations of the module will also need to be found and changed to match the new module.
By name
Connecting signals to a module’s ports by name allows wires to remain correctly connected even if the port list changes. This syntax is more verbose, however.
mod_a instance2 ( .out(wc), .in1(wa), .in2(wb) );
模块例化没有一一.()对应的话就会严格按照声明顺序一一连接
module top_module (
input a,
input b,
output out
);
// Create an instance of "mod_a" named "inst1", and connect ports by name:
mod_a inst1 (
.in1(a), // Port"in1"connects to wire "a"
.in2(b), // Port "in2" connects to wire "b"
.out(out) // Port "out" connects to wire "out"
// (Note: mod_a's port "out" is not related to top_module's wire "out".
// It is simply coincidence that they have the same name)
);
/*
// Create an instance of "mod_a" named "inst2", and connect ports by position:
mod_a inst2 ( a, b, out ); // The three wires are connected to ports in1, in2, and out, respectively.
*/
endmodule
2、Connecting ports by position
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a instance2 (out1,out2,a,b,c,d);
endmodule
3、Connecting ports by name
module top_module (
input a,
input b,
input c,
input d,
output out1,
output out2
);
mod_a instance3 (.out1(out1),.out2(out2),.in1(a),.in2(b),.in3(c),.in4(d));
endmodule
4、Three modules
module top_module (
input clk,
input d,
output q
);
wire a, b; // Create two wires. I called them a and b.
// Create three instances of my_dff, with three different instance names (d1, d2, and d3).
// Connect ports by position: ( input clk, input d, output q)
my_dff d1 ( clk, d, a );
my_dff d2 ( clk, a, b );
my_dff d3 ( clk, b, q );
endmodule
5、Modules and vectors
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
6、Adder1
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cin;
wire [15:0] sum1,sum2;
wire cout1,cout2;
assign cin = 1'b0;
add16 instance1 (.a(a[15:0]),.b(b[15:0]),.cin(cin),.sum(sum1),.cout(cout1));
add16 instance2 (.a(a[31:16]),.b(b[31:16]),.cin(cout1),.sum(sum2),.cout(cout2));
assign sum = {sum2,sum1};
endmodule
7、Adder2
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire cin;
wire cout1;
wire cout2;
wire [15:0] sum1,sum2;
assign cin = 1'b0;
add16 instance0 (a[15:0],b[15:0],cin,sum1,cout1);
add16 instance1 (a[31:16],b[31:16],cout1,sum2,cout2);
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
8、Carry-select adder
One drawback of the ripple carry adder (See previous exercise) 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. 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.
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cin1,cin2,cin3,cout1,cout2,cout3;
wire [15:0] sum1,sum2,sum3;
assign cin1 = 1'b0;
assign cin2 = 1'b0;
assign cin3 = 1'b1;
add16 add1 (a[15:0],b[15:0],cin1,sum1,cout1);
add16 add2 (a[31:16],b[31:16],cin2,sum2,cout2);
add16 add3 (a[31:16],b[31:16],cin3,sum3,cout3);
always@(*)
begin
case(cout1)
1'b0:sum={sum2,sum1};
1'b1:sum={sum3,sum1};
endcase
end
endmodule
9、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.
module top_module(
input [31:0] a,
input [31:0] b,
input sub,
output [31:0] sum
);
wire cout1,cout2;
wire [15:0] sum1,sum2;
wire [31:0] b_n;
assign b_n = b ^ {32{sub}};
add16 add1 (a[15:0],b_n[15:0],sub,sum1,cout1);
add16 add2 (a[31:16],b_n[31:16],cout1,sum2,cout2);
assign sum = {sum2,sum1};
endmodule