本练习的目的是实现算术运算电路。每种电路用2种方法实现:Verilog语言描述和LPM。并比较其不同。
Part I 8-bit的加法器
要求:
- 支持有符号的数的2的补码的形式;
- 带溢出信号,当结果不对时,溢出为1;
代码part1.v
1 /*
2 *(C) yf.x 2010 http://halflife.cnblogs.com
3 *
4 *Complier :Quartus II 9.1
5 *Filename :adder_8b_reg.v
6 *Description:A 8-bit adder,top-level file.which support signed number in 2's complement.
7 *Release :06/30/2010 1.0
8 */
9
10 module adder_8b_reg(SW, //加数A和B
11 KEY, //脉冲和复位
12 LEDR, //和
13 LEDG, //溢出
14 HEX7, //16进制显示加数A
15 HEX6,
16 HEX5, //16进制显示加数B
17 HEX4,
18 HEX1, //16进制显示和
19 HEX0
20 );
21
22 input [15:0]SW;
23 input [1:0]KEY;
24 output [7:0]LEDR;
25 output [8:8]LEDG;
26 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX1,HEX0;
27
28 adder u0(.A(SW[15:8]),
29 .B(SW[7:0]),
30 .clk(KEY[1]),
31 .rst_n(KEY[0]),
32 .sum(LEDR),
33 .overflow(LEDG)
34 );
35
36 seg7_lut u1(.oseg(HEX7),
37 .idig(SW[15:12])
38 );
39 seg7_lut u2(.oseg(HEX6),
40 .idig(SW[11:8])
41 );
42 seg7_lut u3(.oseg(HEX5),
43 .idig(SW[7:4])
44 );
45 seg7_lut u4(.oseg(HEX4),
46 .idig(SW[3:0])
47 );
48 seg7_lut u5(.oseg(HEX1),
49 .idig(LEDR[7:4])
50 );
51 seg7_lut u6(.oseg(HEX0),
52 .idig(LEDR[3:0])
53 );
54
55 endmodule
56
57 /*
58 *(C) yf.x 2010 http://halflife.cnblogs.com
59 *
60 *Complier :Quartus II 9.1
61 *Filename :adder.v
62 *Description:A 8-bit adder,which support signed number in 2's complement.
63 *Release :06/30/2010 1.0
64 */
65
66
67 //=================pins instruction============//
68 // A | SW[15:8] | HEX[7:6]
69 // B | SW[7:0] | HEX[5:4]
70 // clk | KEY[1]
71 // rst_n | KEY[0]
72 // sum | LEDR[7:0] | HEX[1:0]
73 // overflow | LEDG[8]
74 //=============================================//
75 module adder (A,
76 B,
77 clk,
78 rst_n,
79 sum,
80 overflow
81 );
82
83 parameter n=8;
84 input [n-1:0]A,B;
85 input clk,rst_n;
86 output [n-1:0]sum;
87 output overflow;
88 reg overflow;
89 reg [n-1:0]Areg,Breg,Sreg;
90 wire [n-1:0]Sw;
91 wire cout,over_flow;
92
93
94 addern n_bit_adder(0,Areg,Breg,Sw,cout);
95 defparam n_bit_adder.n=8;
96 assign over_flow=cout^Areg[n-1]^Breg[n-1]^Sw[n-1];
97 assign sum=Sreg;
98
99 always @(posedge clk or negedge rst_n)
100 if(!rst_n)
101 begin
102 Areg<=0;
103 Breg<=0;
104 Sreg<=0;
105 overflow<=0;
106 end
107 else
108 begin
109 Areg<=A;
110 Breg<=B;
111 Sreg<=Sw;
112 overflow<=over_flow;
113 end
114 endmodule
115
116 /*
117 *(C) yf.x 2010 http://halflife.cnblogs.com
118 *
119 *Complier :Quartus II 9.1
120 *Filename :addern.v
121 *Description:8-bit 行波进位加法器
122 *Release :06/30/2010 1.0
123 */
124
125 module addern(carryin,X,Y,S,carryout);
126 parameter n=8;
127 input carryin;
128 input [n-1:0]X,Y;
129 output reg [n-1:0]S;
130 output reg carryout;
131 reg [n:0]C;
132 integer k;
133
134 always @(X,Y,carryin)
135 begin
136 C[0]=carryin;
137 for(k=0;k<n;k=k+1)
138 begin
139 S[k]=X[k]^Y[k]^C[k];
140 C[k+1]=(X[k]&Y[k])|(X[k]&C[k])|(Y[k]&C[k]);
141 end
142 carryout=C[n];
143 end
144
145
146 endmodule
147
148
149
图1 part1编译结果
这部分要注意的就是2的补码的表示,和溢出信号的推导。可参阅Reference【1】。
Part II 加、减电路
要求:
在part I的基础上修改,使其可做加、减运算。
代码part2.v
1 /*
2 *(C) yf.x 2010 http://halflife.cnblogs.com
3 *
4 *Complier :Quartus II 9.1
5 *Filename :part2.v
6 *Description:Top-level file of addersubtractor circuit.
7 *Release :06/30/2010 1.0
8 */
9
10 module part2 (SW, //加数A和B
11 KEY, //脉冲和复位
12 LEDR, //和
13 LEDG, //溢出
14 HEX7, //16进制显示加数A
15 HEX6,
16 HEX5, //16进制显示加数B
17 HEX4,
18 HEX1, //16进制显示和
19 HEX0
20 );
21
22 input [16:0]SW;
23 input [1:0]KEY;
24 output [7:0]LEDR;
25 output [8:8]LEDG;
26 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX1,HEX0;
27 wire [7:0]sum;
28
29 addersubtractor u0(.A(SW[15:8]),
30 .B(SW[7:0]),
31 .clk(KEY[1]),
32 .rst_n(KEY[0]),
33 .S(sum),
34 .overflow(LEDG),
35 .addsub(SW[16])
36 );
37
38 assign LEDR=sum;
39
40 seg7_lut u1(.oseg(HEX7),
41 .idig(SW[15:12])
42 );
43 seg7_lut u2(.oseg(HEX6),
44 .idig(SW[11:8])
45 );
46 seg7_lut u3(.oseg(HEX5),
47 .idig(SW[7:4])
48 );
49 seg7_lut u4(.oseg(HEX4),
50 .idig(SW[3:0])
51 );
52 seg7_lut u5(.oseg(HEX1),
53 .idig(sum[7:4])
54 );
55 seg7_lut u6(.oseg(HEX0),
56 .idig(sum[3:0])
57 );
58
59 endmodule
60
61 /*
62 *(C) yf.x 2010 http://halflife.cnblogs.com
63 *
64 *Complier :Quartus II 9.1
65 *Filename :addersubtractor.v
66 *Description:addersubtractor ciucuit.
67 *Release :06/30/2010 1.0
68 */
69
70 //Top-level module
71 module addersubtractor(A,
72 B,
73 clk,
74 rst_n,
75 addsub, //0=+,1=-;
76 S,
77 overflow
78 );
79 parameter n=8;
80 input [n-1:0]A,B;
81 input clk,rst_n,addsub;
82 output [n-1:0]S;
83 output overflow;
84
85 reg addsub_r,overflow;
86 reg [n-1:0]Areg,Breg,Sreg;
87 wire [n-1:0]G, H,M;
88 wire cout,over_flow;
89
90 //Define combinational logic circuit
91 assign H=Breg^{n{addsub_r}},G=Areg;
92 addern u0(addsub_r,G,H,M,cout);
93 defparam u0.n=n;
94 assign over_flow=cout^G[n-1]^H[n-1]^M[n-1];
95 assign S=Sreg;
96
97 //Define flip-flops and registers
98 always @(posedge clk or negedge rst_n)
99 if(!rst_n)
100 begin
101 Areg<=0;
102 Breg<=0;
103 Sreg<=0;
104 overflow<=0;
105 addsub_r<=0;
106 end
107 else
108 begin
109 Areg<=A;
110 Breg<=B;
111 Sreg<=M;
112 overflow<=over_flow;
113 addsub_r<=addsub;
114 end
115 endmodule
图2 Part II编译结果
这部分,很简单,由2的补码表示可知,减法运算变为加法,只需要在part I加一个控制信号add_sub,并将其作为cin,当其为1时,即为减法。
Part III 使用lpm_add_sub实现Part I
代码part3.v
1 //Top-level file
2 module part3 (SW, //加数A和B
3 KEY, //脉冲和复位
4 LEDR, //和
5 LEDG, //溢出
6 HEX7, //16进制显示加数A
7 HEX6,
8 HEX5, //16进制显示加数B
9 HEX4,
10 HEX1, //16进制显示和
11 HEX0
12 );
13
14 input [15:0]SW;
15 input [1:0]KEY;
16 output [7:0]LEDR;
17 output [8:8]LEDG;
18 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX1,HEX0;
19
20 reg [7:0]Areg,Breg,Sreg;
21 wire over_flow;
22 wire [7:0]S,H,M;
23
24 assign LEDR=S;
25 assign LEDG=over_flow;
26 assign H=Areg,M=Breg;
27
28 lpa_add8 nbit_adder(.cin(0),
29 .dataa(H[7:0]),
30 .datab(M[7:0]),
31 .overflow(over_flow),
32 .result(S)
33 );
34
35 always @(posedge KEY[1] or negedge KEY[0])
36 if(!KEY[0])
37 begin
38 Areg<=0;
39 Breg<=0;
40 Sreg<=0;
41
42 end
43 else
44 begin
45 Areg<=SW[15:8];
46 Breg<=SW[7:0];
47 Sreg<=S;
48
49 end
50
51 seg7_lut u1(.oseg(HEX7),
52 .idig(H[7:4])
53 );
54 seg7_lut u2(.oseg(HEX6),
55 .idig(H[3:0])
56 );
57 seg7_lut u3(.oseg(HEX5),
58 .idig(M[7:4])
59 );
60 seg7_lut u4(.oseg(HEX4),
61 .idig(M[3:0])
62 );
63 seg7_lut u5(.oseg(HEX1),
64 .idig(S[7:4])
65 );
66 seg7_lut u6(.oseg(HEX0),
67 .idig(S[3:0])
68 );
69
70 endmodule
71
72 // synopsys translate_off
73 `timescale 1 ps / 1 ps
74 // synopsys translate_on
75 module lpa_add8 (
76 cin,
77 dataa,
78 datab,
79 overflow,
80 result);
81
82 input cin;
83 input [7:0] dataa;
84 input [7:0] datab;
85 output overflow;
86 output [7:0] result;
87
88 wire sub_wire0;
89 wire [7:0] sub_wire1;
90 wire overflow = sub_wire0;
91 wire [7:0] result = sub_wire1[7:0];
92
93 lpm_add_sub lpm_add_sub_component (
94 .dataa (dataa),
95 .datab (datab),
96 .cin (cin),
97 .overflow (sub_wire0),
98 .result (sub_wire1)
99 // synopsys translate_off
100 ,
101 .aclr (),
102 .add_sub (),
103 .clken (),
104 .clock (),
105 .cout ()
106 // synopsys translate_on
107 );
108 defparam
109 lpm_add_sub_component.lpm_direction = "ADD",
110 lpm_add_sub_component.lpm_hint = "ONE_INPUT_IS_CONSTANT=NO,CIN_USED=YES",
111 lpm_add_sub_component.lpm_representation = "SIGNED",
112 lpm_add_sub_component.lpm_type = "LPM_ADD_SUB",
113 lpm_add_sub_component.lpm_width = 8;
114
115
116 endmodule
Part IV 用lpm_add_sub实现Part II
代码part4.v
1 module part4 (SW, //加数A和B
2 KEY, //脉冲和复位
3 LEDR, //和
4 LEDG, //溢出
5 HEX7, //16进制显示加数A
6 HEX6,
7 HEX5, //16进制显示加数B
8 HEX4,
9 HEX1, //16进制显示和
10 HEX0
11 );
12
13 input [16:0]SW;
14 input [1:0]KEY;
15 output [7:0]LEDR;
16 output [8:8]LEDG;
17 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX1,HEX0;
18 wire [7:0]sum;
19 reg [7:0]Areg,Breg,Sreg;
20 wire over_flow,cout;
21 wire [7:0]Aw,Bw;
22
23
24 assign Aw=Areg,Bw=Breg;
25
26
27 always @(posedge KEY[1] or negedge KEY[0])
28 begin
29 if(!KEY[0])
30 begin
31 Areg<=0;
32 Breg<=0;
33 Sreg<=0;
34 end
35 else
36 begin
37 Areg<=SW[15:8];
38 Breg<=SW[7:0];
39 Sreg<=sum;
40 end
41 end
42
43
44 lpm_addsub u0(.dataa(Aw),
45 .datab(Bw),
46 .cin(~SW[16]),
47 .cout(cout),
48 .result(sum),
49 .overflow(over_flow),
50 .add_sub(SW[16])
51 );
52
53 assign LEDR=sum,LEDG=over_flow;
54
55 seg7_lut u1(.oseg(HEX7),
56 .idig(SW[15:12])
57 );
58 seg7_lut u2(.oseg(HEX6),
59 .idig(SW[11:8])
60 );
61 seg7_lut u3(.oseg(HEX5),
62 .idig(SW[7:4])
63 );
64 seg7_lut u4(.oseg(HEX4),
65 .idig(SW[3:0])
66 );
67 seg7_lut u5(.oseg(HEX1),
68 .idig(sum[7:4])
69 );
70 seg7_lut u6(.oseg(HEX0),
71 .idig(sum[3:0])
72 );
73
74 endmodule
75
76 // synopsys translate_off
77 `timescale 1 ps / 1 ps
78 // synopsys translate_on
79 module lpm_addsub (
80 add_sub,
81 cin,
82 dataa,
83 datab,
84 cout,
85 overflow,
86 result);
87
88 input add_sub;
89 input cin;
90 input [7:0] dataa;
91 input [7:0] datab;
92 output cout;
93 output overflow;
94 output [7:0] result;
95
96 wire sub_wire0;
97 wire sub_wire1;
98 wire [7:0] sub_wire2;
99 wire overflow = sub_wire0;
100 wire cout = sub_wire1;
101 wire [7:0] result = sub_wire2[7:0];
102
103 lpm_add_sub lpm_add_sub_component (
104 .dataa (dataa),
105 .add_sub (add_sub),
106 .datab (datab),
107 .cin (cin),
108 .overflow (sub_wire0),
109 .cout (sub_wire1),
110 .result (sub_wire2)
111 // synopsys translate_off
112 ,
113 .aclr (),
114 .clken (),
115 .clock ()
116 // synopsys translate_on
117 );
118 defparam
119 lpm_add_sub_component.lpm_direction = "UNUSED",
120 lpm_add_sub_component.lpm_hint = "ONE_INPUT_IS_CONSTANT=NO,CIN_USED=YES",
121 lpm_add_sub_component.lpm_representation = "SIGNED",
122 lpm_add_sub_component.lpm_type = "LPM_ADD_SUB",
123 lpm_add_sub_component.lpm_width = 8;
124
125
126 endmodule
127
128 // ============================================================
129 // CNX file r
图3 Part IV时序分析
Part V 4X4乘法器
代码part5.v
1 //Top-level file
2 module part5(SW, //SW[11:8]=A,SW[3:0]=B
3 HEX6, //A
4 HEX4, //B
5 HEX1, //P
6 HEX0
7 );
8
9 input [11:0]SW;
10 output [6:0]HEX6,HEX4,HEX1,HEX0;
11 wire [7:0]P;
12
13 multiplier u0(SW[11:8],SW[3:0],P);
14 seg7_lut A(.oseg(HEX6),
15 .idig(SW[11:8])
16 );
17 seg7_lut B(.oseg(HEX4),
18 .idig(SW[3:0])
19 );
20 seg7_lut p1(.oseg(HEX1),
21 .idig(P[7:4])
22 );
23 seg7_lut p0(.oseg(HEX0),
24 .idig(P[3:0])
25 );
26 endmodule
27
28 //multiplier
29 module multiplier(A,B,P);
30 input [3:0]A,B;
31 output [7:0]P;
32
33 wire [3:1]ctop,csecond,cbottom;
34 wire [5:2]pp1;
35 wire [6:3]pp2;
36
37 assign P[0]=A[0]&B[0];
38
39 u0 toprow_stage0(A[1],A[0],B[1],B[0],0,ctop[1],P[1]);
40 u0 toprow_stage1(A[2],A[1],B[1],B[0],ctop[1],ctop[2],pp1[2]);
41 u0 toprow_stage2(A[3],A[2],B[1],B[0],ctop[2],ctop[3],pp1[3]);
42 u0 toprow_stage3(0,A[3],B[1],B[0],ctop[3],pp1[5],pp1[4]);
43 u1 secondrow_stage0(pp1[2],A[0],B[2],0,csecond[1],P[2]);
44 u1 secondrow_stage1(pp1[3],A[1],B[2],csecond[1],csecond[2],pp2[3]);
45 u1 secondrow_stage2(pp1[4],A[2],B[2],csecond[2],csecond[3],pp2[4]);
46 u1 secondrow_stage3(pp1[5],A[3],B[2],csecond[3],pp2[6],pp2[5]);
47 u1 bottomrow_stage0(pp2[3],A[0],B[3],0,cbottom[1],P[3]);
48 u1 bottomrow_stage1(pp2[4],A[1],B[3],cbottom[1],cbottom[2],P[4]);
49 u1 bottomrow_stage2(pp2[5],A[2],B[3],cbottom[2],cbottom[3],P[5]);
50 u1 bottomrow_stage3(pp2[6],A[3],B[3],cbottom[3],P[7],P[6]);
51
52 endmodule
53
54 module u0(a_k1,a_k,b1,b0,cin,cout,s);
55 input a_k1,a_k,b1,b0,cin;
56 output cout,s;
57 wire x,y;
58
59 assign x=a_k1&b0;
60 assign y=a_k&b1;
61
62 fulladd FA(cin,x,y,cout,s);
63
64 endmodule
65
66 module u1(ppi_k1,a_k,bj,cin,cout,s);
67 input ppi_k1,a_k,bj,cin;
68 output cout,s;
69
70 wire y;
71
72 assign y=bj&a_k;
73
74 fulladd FA(cin,ppi_k1,y,cout,s);
75
76 endmodule
77
78 module fulladd(cin,a,b,cout,s);
79 input cin,a,b;
80 output reg cout,s;
81
82 always @(cin,a,b)
83 {cout,s}=a+b+cin;
84
85 endmodule
图4 part V仿真
Part VI 8X8乘法器
代码part6.v
1 //Top-level file
2 module part6(SW,
3 KEY,
4 HEX7,
5 HEX6,
6 HEX5,
7 HEX4,
8 HEX3,
9 HEX2,
10 HEX1,
11 HEX0
12 );
13
14 input [15:0]SW; //A,B
15 input [1:0]KEY; //clk & rst_n
16 output [6:0]HEX7,HEX6, //A
17 HEX5,HEX4, //B
18 HEX3,HEX2,HEX1,HEX0; //P
19
20 reg [7:0]Areg,Breg;
21 reg [15:0]Preg;
22 wire [7:0]Aw,Bw;
23 wire [15:0]Pw,P;
24
25 always @(posedge KEY[1] or negedge KEY[0])
26 if(!KEY[0])
27 begin
28 Areg<=0;
29 Breg<=0;
30 Preg<=0;
31 end
32 else
33 begin
34 Areg<=SW[15:8];
35 Breg<=SW[7:0];
36 Preg<=Pw;
37 end
38
39 assign Aw=Areg,Bw=Breg,P=Preg;
40
41 multiplier_8X8 mt(.A(Aw),
42 .B(Bw),
43 .P(Pw)
44 );
45
46 seg7_lut h7(.oseg(HEX7),
47 .idig(Aw[7:4])
48 );
49 seg7_lut h6(.oseg(HEX6),
50 .idig(Aw[3:0])
51 );
52 seg7_lut h5(.oseg(HEX5),
53 .idig(Bw[7:4])
54 );
55 seg7_lut h4(.oseg(HEX4),
56 .idig(Bw[3:0])
57 );
58 seg7_lut h3(.oseg(HEX3),
59 .idig(P[15:12])
60 );
61 seg7_lut h2(.oseg(HEX2),
62 .idig(P[11:8])
63 );
64 seg7_lut h1(.oseg(HEX1),
65 .idig(P[7:4])
66 );
67 seg7_lut h0(.oseg(HEX0),
68 .idig(P[3:0])
69 );
70
71 endmodule
72
73 //multiplier_8X8.v
74 module multiplier_8X8(A,
75 B,
76 P,
77 );
78
79 input [7:0]A,B;
80 output [15:0]P;
81
82 wire [7:1]c1,c2,c3,c4,c5,c6,c7;
83 wire [9:2]pp1;
84 wire [10:3]pp2;
85 wire [11:4]pp3;
86 wire [12:5]pp4;
87 wire [13:6]pp5;
88 wire [14:7]pp6;
89
90 assign P[0]=A[0]&B[0];
91
92 u0 row1_stage0(A[1],A[0],B[1],B[0],0,c1[1],P[1]);
93 u0 row1_stage1(A[2],A[1],B[1],B[0],c1[1],c1[2],pp1[2]);
94 u0 row1_stage2(A[3],A[2],B[1],B[0],c1[2],c1[3],pp1[3]);
95 u0 row1_stage3(A[4],A[3],B[1],B[0],c1[3],c1[4],pp1[4]);
96 u0 row1_stage4(A[5],A[4],B[1],B[0],c1[4],c1[5],pp1[5]);
97 u0 row1_stage5(A[6],A[5],B[1],B[0],c1[5],c1[6],pp1[6]);
98 u0 row1_stage6(A[7],A[6],B[1],B[0],c1[6],c1[7],pp1[7]);
99 u0 row1_stage7(0,A[7],B[1],B[0],c1[7],pp1[9],pp1[8]);
100
101 u1 row2_stage0(pp1[2],A[0],B[2],0,c2[1],P[2]);
102 u1 row2_stage1(pp1[3],A[1],B[2],c2[1],c2[2],pp2[3]);
103 u1 row2_stage2(pp1[4],A[2],B[2],c2[2],c2[3],pp2[4]);
104 u1 row2_stage3(pp1[5],A[3],B[2],c2[3],c2[4],pp2[5]);
105 u1 row2_stage4(pp1[6],A[4],B[2],c2[4],c2[5],pp2[6]);
106 u1 row2_stage5(pp1[7],A[5],B[2],c2[5],c2[6],pp2[7]);
107 u1 row2_stage6(pp1[8],A[6],B[2],c2[6],c2[7],pp2[8]);
108 u1 row2_stage7(pp1[9],A[7],B[2],c2[7],pp2[10],pp2[9]);
109
110 u1 row3_stage0(pp2[3],A[0],B[3],0,c3[1],P[3]);
111 u1 row3_stage1(pp2[4],A[1],B[3],c3[1],c3[2],pp3[4]);
112 u1 row3_stage2(pp2[5],A[2],B[3],c3[2],c3[3],pp3[5]);
113 u1 row3_stage3(pp2[6],A[3],B[3],c3[3],c3[4],pp3[6]);
114 u1 row3_stage4(pp2[7],A[4],B[3],c3[4],c3[5],pp3[7]);
115 u1 row3_stage5(pp2[8],A[5],B[3],c3[5],c3[6],pp3[8]);
116 u1 row3_stage6(pp2[9],A[6],B[3],c3[6],c3[7],pp3[9]);
117 u1 row3_stage7(pp2[10],A[7],B[3],c3[7],pp3[11],pp3[10]);
118
119 u1 row4_stage0(pp3[4],A[0],B[4],0,c4[1],P[4]);
120 u1 row4_stage1(pp3[5],A[1],B[4],c4[1],c4[2],pp4[5]);
121 u1 row4_stage2(pp3[6],A[2],B[4],c4[2],c4[3],pp4[6]);
122 u1 row4_stage3(pp3[7],A[3],B[4],c4[3],c4[4],pp4[7]);
123 u1 row4_stage4(pp3[8],A[4],B[4],c4[4],c4[5],pp4[8]);
124 u1 row4_stage5(pp3[9],A[5],B[4],c4[5],c4[6],pp4[9]);
125 u1 row4_stage6(pp3[10],A[6],B[4],c4[6],c4[7],pp4[10]);
126 u1 row4_stage7(pp3[11],A[7],B[4],c4[7],pp4[12],pp4[11]);
127
128 u1 row5_stage0(pp4[5],A[0],B[5],0,c5[1],P[5]);
129 u1 row5_stage1(pp4[6],A[1],B[5],c5[1],c5[2],pp5[6]);
130 u1 row5_stage2(pp4[7],A[2],B[5],c5[2],c5[3],pp5[7]);
131 u1 row5_stage3(pp4[8],A[3],B[5],c5[3],c5[4],pp5[8]);
132 u1 row5_stage4(pp4[9],A[4],B[5],c5[4],c5[5],pp5[9]);
133 u1 row5_stage5(pp4[10],A[5],B[5],c5[5],c5[6],pp5[10]);
134 u1 row5_stage6(pp4[11],A[6],B[5],c5[6],c5[7],pp5[11]);
135 u1 row5_stage7(pp4[12],A[7],B[5],c5[7],pp5[13],pp5[12]);
136
137 u1 row6_stage0(pp5[6],A[0],B[6],0,c6[1],P[6]);
138 u1 row6_stage1(pp5[7],A[1],B[6],c6[1],c6[2],pp6[7]);
139 u1 row6_stage2(pp5[8],A[2],B[6],c6[2],c6[3],pp6[8]);
140 u1 row6_stage3(pp5[9],A[3],B[6],c6[3],c6[4],pp6[9]);
141 u1 row6_stage4(pp5[10],A[4],B[6],c6[4],c6[5],pp6[10]);
142 u1 row6_stage5(pp5[11],A[5],B[6],c6[5],c6[6],pp6[11]);
143 u1 row6_stage6(pp5[12],A[6],B[6],c6[6],c6[7],pp6[12]);
144 u1 row6_stage7(pp5[13],A[7],B[6],c6[7],pp6[14],pp6[13]);
145
146 u1 row7_stage0(pp6[7],A[0],B[7],0,c7[1],P[7]);
147 u1 row7_stage1(pp6[8],A[1],B[7],c7[1],c7[2],P[8]);
148 u1 row7_stage2(pp6[9],A[2],B[7],c7[2],c7[3],P[9]);
149 u1 row7_stage3(pp6[10],A[3],B[7],c7[3],c7[4],P[10]);
150 u1 row7_stage4(pp6[11],A[4],B[7],c7[4],c7[5],P[11]);
151 u1 row7_stage5(pp6[12],A[5],B[7],c7[5],c7[6],P[12]);
152 u1 row7_stage6(pp6[13],A[6],B[7],c7[6],c7[7],P[13]);
153 u1 row7_stage7(pp6[14],A[7],B[7],c7[7],P[15],P[14]);
154
155
156 endmodule
157
158 module u0(a_k1,a_k,b1,b0,cin,cout,s);
159 input a_k1,a_k,b1,b0,cin;
160 output cout,s;
161 wire x,y;
162
163 assign x=a_k1&b0;
164 assign y=a_k&b1;
165
166 fulladd FA(cin,x,y,cout,s);
167
168 endmodule
169
170 module u1(ppi_k1,a_k,bj,cin,cout,s);
171 input ppi_k1,a_k,bj,cin;
172 output cout,s;
173
174 wire y;
175
176 assign y=bj&a_k;
177
178 fulladd FA(cin,ppi_k1,y,cout,s);
179
180 endmodule
181
182 module fulladd(cin,a,b,cout,s);
183 input cin,a,b;
184 output reg cout,s;
185
186 always @(cin,a,b)
187 {cout,s}=a+b+cin;
188
189 endmodule
图5 part VI时序分析
Part VII 用lpm_mult实现Part VI
代码part7.v
1 //Top-level file
2 module part7(SW,
3 KEY,
4 HEX7,
5 HEX6,
6 HEX5,
7 HEX4,
8 HEX3,
9 HEX2,
10 HEX1,
11 HEX0
12 );
13
14 input [15:0]SW; //A,B
15 input [1:0]KEY; //clk & rst_n
16 output [6:0]HEX7,HEX6, //A
17 HEX5,HEX4, //B
18 HEX3,HEX2,HEX1,HEX0; //P
19
20 reg [7:0]Areg,Breg;
21 reg [15:0]Preg;
22 wire [7:0]Aw,Bw;
23 wire [15:0]Pw,P;
24
25 always @(posedge KEY[1] or negedge KEY[0])
26 if(!KEY[0])
27 begin
28 Areg<=0;
29 Breg<=0;
30 Preg<=0;
31 end
32 else
33 begin
34 Areg<=SW[15:8];
35 Breg<=SW[7:0];
36 Preg<=Pw;
37 end
38
39 assign Aw=Areg,Bw=Breg,P=Preg;
40
41 mult mt(.dataa(Aw),
42 .datab(Bw),
43 .result(Pw)
44 );
45
46 seg7_lut h7(.oseg(HEX7),
47 .idig(Aw[7:4])
48 );
49 seg7_lut h6(.oseg(HEX6),
50 .idig(Aw[3:0])
51 );
52 seg7_lut h5(.oseg(HEX5),
53 .idig(Bw[7:4])
54 );
55 seg7_lut h4(.oseg(HEX4),
56 .idig(Bw[3:0])
57 );
58 seg7_lut h3(.oseg(HEX3),
59 .idig(P[15:12])
60 );
61 seg7_lut h2(.oseg(HEX2),
62 .idig(P[11:8])
63 );
64 seg7_lut h1(.oseg(HEX1),
65 .idig(P[7:4])
66 );
67 seg7_lut h0(.oseg(HEX0),
68 .idig(P[3:0])
69 );
70
71 endmodule
72
73 `timescale 1 ps / 1 ps
74 // synopsys translate_on
75 module mult (
76 dataa,
77 datab,
78 result);
79
80 input [7:0] dataa;
81 input [7:0] datab;
82 output [15:0] result;
83
84 wire [15:0] sub_wire0;
85 wire [15:0] result = sub_wire0[15:0];
86
87 lpm_mult lpm_mult_component (
88 .dataa (dataa),
89 .datab (datab),
90 .result (sub_wire0),
91 .aclr (1'b0),
92 .clken (1'b1),
93 .clock (1'b0),
94 .sum (1'b0));
95 defparam
96 lpm_mult_component.lpm_hint = "MAXIMIZE_SPEED=5",
97 lpm_mult_component.lpm_representation = "UNSIGNED",
98 lpm_mult_component.lpm_type = "LPM_MULT",
99 lpm_mult_component.lpm_widtha = 8,
100 lpm_mult_component.lpm_widthb = 8,
101 lpm_mult_component.lpm_widthp = 16;
102
103
104 endmodule
图6 part VII使用的LEs
图7 part Vii时序分析
Part VIII 四则运算
要求:
用lpm_add_sub和lpm_mult实现S=(AXB)+(CXD)
代码part8.v
1 //top-level file
2 //yes-done
3 module part8(SW,
4 HEX7,
5 HEX6,
6 HEX5,
7 HEX4,
8 HEX3,
9 HEX2,
10 HEX1,
11 HEX0,
12 KEY,
13 LEDG
14 );
15
16 input [17:0]SW;
17 input [1:0]KEY;
18 output [8:8]LEDG;
19 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0;
20
21 reg [7:0]Areg,Breg,Creg,Dreg;
22 reg [15:0]S;
23 reg cout;
24 wire [15:0]p1,p2;
25 wire [15:0]sum;
26 wire c;
27
28 mult u0(Areg,Breg,p1);
29 mult u1(Creg,Dreg,p2);
30 add u3(p1,p2,c,sum);
31
32 assign LEDG=cout;
33
34 always @(posedge KEY[1] or negedge KEY[0])
35 begin
36 if(!KEY[0])
37 begin
38 Areg<=0;
39 Breg<=0;
40 Creg<=0;
41 Dreg<=0;
42 cout<=0;
43 S<=0;
44 end
45 else
46
47 if(SW[17])
48 begin
49 if(SW[16])
50 begin
51 Areg<=SW[15:8];
52 Breg<=SW[7:0];
53 Creg<=Creg;
54 Dreg<=Dreg;
55 cout<=c;
56 S<=sum;
57 end
58 else
59 begin
60 Areg<=Areg;
61 Breg<=Breg;
62 Creg<=SW[15:8];
63 Dreg<=SW[7:0];
64 cout<=c;
65 S<=sum;
66 end
67 end
68 else
69 begin
70 Areg<=Areg;
71 Breg<=Breg;
72 Creg<=Creg;
73 Dreg<=Dreg;
74 cout<=c;
75 S<=sum;
76 end
77 end
78
79 seg7_lut H7(.idig(SW[16]?Areg[7:4]:Creg[7:4]),
80 .oseg(HEX7)
81 );
82 seg7_lut H6(.idig(SW[16]?Areg[3:0]:Creg[3:0]),
83 .oseg(HEX6)
84 );
85 seg7_lut H5(.idig(SW[16]?Breg[7:4]:Dreg[7:4]),
86 .oseg(HEX5)
87 );
88 seg7_lut H4(.idig(SW[16]?Breg[3:0]:Dreg[3:0]),
89 .oseg(HEX4)
90 );
91 seg7_lut H3(.idig(S[15:12]),
92 .oseg(HEX3)
93 );
94 seg7_lut H2(.idig(S[11:8]),
95 .oseg(HEX2)
96 );
97 seg7_lut H1(.idig(S[7:4]),
98 .oseg(HEX1)
99 );
100 seg7_lut H0(.idig(S[3:0]),
101 .oseg(HEX0)
102 );
103
104 endmodule
图8 partViii时序分析
图9 指定fmax后的时序分析
Part IX 用lpm_mult_add实现Part VIII
代码part9.v
1 //Top-level file
2
3 module part9(SW,
4 HEX7,
5 HEX6,
6 HEX5,
7 HEX4,
8 HEX3,
9 HEX2,
10 HEX1,
11 HEX0,
12 KEY,
13 LEDG
14 );
15
16 input [17:0]SW;
17 input [1:0]KEY;
18 output [8:8]LEDG;
19 output [6:0]HEX7,HEX6,HEX5,HEX4,HEX3,HEX2,HEX1,HEX0;
20
21
22
23 reg [7:0]A,B,C,D;
24
25 wire [15:0]sum;
26
27 always @(posedge KEY[1] or negedge KEY[0])
28 if(!KEY[0])
29 begin
30 A<=0;
31 B<=0;
32 C<=0;
33 D<=0;
34 end
35 else
36 begin
37 if(SW[17])
38 begin
39 if(SW[16])
40 begin
41 A<=SW[15:8];
42 B<=SW[7:0];
43 C<=C;
44 D<=D;
45 end
46 else
47 begin
48 A<=A;
49 B<=B;
50 C<=SW[15:8];
51 D<=SW[7:0];
52 end
53 end
54 else
55 begin
56 A<=A;
57 B<=B;
58 C<=C;
59 D<=D;
60 end
61 end
62
63
64 m_a u0(
65 .aclr0(~KEY[0]),
66 .clock0(KEY[1]),
67 .dataa_0(C),
68 .dataa_1(A),
69 .datab_0(D),
70 .datab_1(B),
71 .result({LEDG,sum})
72 );
73
74
75
76 seg7_lut H7(.idig(SW[16]?A[7:4]:C[7:4]),
77 .oseg(HEX7)
78 );
79 seg7_lut H6(.idig(SW[16]?A[3:0]:C[3:0]),
80 .oseg(HEX6)
81 );
82 seg7_lut H5(.idig(SW[16]?B[7:4]:D[7:4]),
83 .oseg(HEX5)
84 );
85 seg7_lut H4(.idig(SW[16]?B[3:0]:D[3:0]),
86 .oseg(HEX4)
87 );
88 seg7_lut H3(.idig(sum[15:12]),
89 .oseg(HEX3)
90 );
91 seg7_lut H2(.idig(sum[11:8]),
92 .oseg(HEX2)
93 );
94 seg7_lut H1(.idig(sum[7:4]),
95 .oseg(HEX1)
96 );
97 seg7_lut H0(.idig(sum[3:0]),
98 .oseg(HEX0)
99 );
100
101 endmodule
图10 part IX仿真
Conclusion
这个练习时到目前为止最繁琐的,有的题海的意思,没办法,熟能生巧。断断续续,花了一周才完成。很多细节确实做了才知道,很多文章用的时候再翻阅,会有新的理解。
Reference
【1】《数字逻辑基础与Verilog HDL设计》--chapter 5 夏宇闻,译
夏译版的很不错了,yy一下,如果笔法有侯捷先生的风格,。。。
【2】《Using Library Modules in Verilog Designs》
【3】《Timing Considerations with Verilog-Based Designs》