乘法器的verilog实现(并⾏、移位相加、查找表)并⾏乘法器,也就是⽤乘法运算符实现,下⾯的代码实现8bit⽆符号数的乘法。
代码:
1module mult_parrell(rst_n,
太空舞步教程
2 clk,
3 a,
4 b,
5 p
6 );
7parameter DATA_SIZE = 8;
8
9input rst_n;
星期日的英文
10input clk;
11input [DATA_SIZE - 1 : 0] a;
12input [DATA_SIZE - 1 : 0] b;
13
14output [2*DATA_SIZE - 1 : 0] p;
15
16reg [DATA_SIZE - 1 : 0] a_r;
17reg [DATA_SIZE - 1 : 0] b_r;
18
19wire [2*DATA_SIZE - 1 : 0] p_tmp;
20reg [2*DATA_SIZE - 1 : 0] p;
21
22//输⼊数据打⼀拍
23always@(podge clk)
24if(!rst_n)
25begin
26 a_r <= 8'd0;
27 b_r <= 8'd0;
28end
29el
30begin
31 a_r <= a;
32 b_r <= b;
33end
34
35assign p_tmp = a*b; //只能做⽆符号数的相乘,若要做有符号数乘法,需将数据声明为signed类型
36
37//输出数据打⼀拍
38always@(podge clk)
39if(!rst_n)
40begin
41 p <= 16'd0;
42end
43el
44begin
45 p <= p_tmp;
46end
47
48endmodule
移位相加乘法器,下⾯的代码可实现8bit有符号数的相乘,注意符号扩展以及MSB位的处理:
//输⼊数据取反
assign a_r_inv = ~a_r + 1;
assign a_shift0 = b_r[0] ? {{8{a_r[7]}},a_r} : 0;
assign a_shift1 = b_r[1] ? {{7{a_r[7]}},a_r,1'b0} : 0;
assign a_shift2 = b_r[2] ? {{6{a_r[7]}},a_r,2'b0} : 0;
assign a_shift3 = b_r[3] ? {{5{a_r[7]}},a_r,3'b0} : 0;
assign a_shift4 = b_r[4] ? {{4{a_r[7]}},a_r,4'b0} : 0;
assign a_shift5 = b_r[5] ? {{3{a_r[7]}},a_r,5'b0} : 0;
assign a_shift6 = b_r[6] ? {{2{a_r[7]}},a_r,6'b0} : 0;
assign a_shift7 = b_r[7] ? {{1{a_r_inv[7]}},a_r_inv,7'b0} : 0; //被乘数为⽆符号数时,特别处理
代码:
1module mult_shift_add(rst_n,
2 clk,
3 a,
4 b,
5 p
6 );
7parameter DATA_SIZE = 8;
8
9input rst_n;
10input clk;
11input [DATA_SIZE - 1 : 0] a;
12input [DATA_SIZE - 1 : 0] b;
13
14output [2*DATA_SIZE - 2 : 0] p;
15
16//输⼊数据打⼀个时钟节拍
17reg [DATA_SIZE - 1 : 0] a_r;
18reg [DATA_SIZE - 1 : 0] b_r;
19
20//输⼊数据取反
21wire [DATA_SIZE - 1 : 0] a_r_inv;
22
23//输⼊数据移位
24wire [2*DATA_SIZE - 1 : 0] a_shift0;
25wire [2*DATA_SIZE - 1 : 0] a_shift1;
26wire [2*DATA_SIZE - 1 : 0] a_shift2;
27wire [2*DATA_SIZE - 1 : 0] a_shift3;
28wire [2*DATA_SIZE - 1 : 0] a_shift4;
29wire [2*DATA_SIZE - 1 : 0] a_shift5;
30wire [2*DATA_SIZE - 1 : 0] a_shift6;
31wire [2*DATA_SIZE - 1 : 0] a_shift7;
32
33//输出数据打⼀个时钟节拍
34wire [2*DATA_SIZE - 1 : 0] p_tmp;
35reg [2*DATA_SIZE - 1 : 0] p;
36
37//输⼊数据打⼀个时钟节拍
38always@(podge clk)
39if(!rst_n)
40begin
41 a_r <= 8'd0;
42 b_r <= 8'd0;
43end
44el
45begin
46 a_r <= a;
47 b_r <= b;
48end
inform
49//输⼊数据取反
50assign a_r_inv = ~a_r + 1;
51
52//输⼊数据移位,注意符号扩展,不仅仅是最⾼位扩展
53//对每⼀个bit都需扩展
54assign a_shift0 = b_r[0] ? {{8{a_r[7]}},a_r} : 0;
55assign a_shift1 = b_r[1] ? {{7{a_r[7]}},a_r,1'b0} : 0;sheep是什么意思
56assign a_shift2 = b_r[2] ? {{6{a_r[7]}},a_r,2'b0} : 0;
57assign a_shift3 = b_r[3] ? {{5{a_r[7]}},a_r,3'b0} : 0;
58assign a_shift4 = b_r[4] ? {{4{a_r[7]}},a_r,4'b0} : 0;
59assign a_shift5 = b_r[5] ? {{3{a_r[7]}},a_r,5'b0} : 0;
60assign a_shift6 = b_r[6] ? {{2{a_r[7]}},a_r,6'b0} : 0;
61assign a_shift7 = b_r[7] ? {{1{a_r_inv[7]}},a_r_inv,7'b0} : 0; //被乘数为⽆符号数时,特别处理62
bathroom怎么读63assign p_tmp = a_shift0 + a_shift1 + a_shift2 + a_shift3 + a_shift4
64 + a_shift5 + a_shift6 + a_shift7;
65
66always@(podge clk)
67if(!rst_n)
68begin
69//p <= 16'd0;
70 p <= 15'd0;
71end
72el
73begin
74//p <= p_tmp[15:0];
75 p <= p_tmp[14:0];
76end
77
78endmodule
testbench:
1module mult_shift_add_tb;
2
3// Inputs
4reg rst_n;
5reg clk;
6reg [7:0] a;
7reg [7:0] b;
8
9// Outputs
10wire [14:0] p;
11
12// Instantiate the Unit Under Test (UUT)
13 mult_shift_add uut (
14 .rst_n(rst_n),
15 .clk(clk),
16 .a(a),
17 .b(b),
18 .p(p)
19 );
20
21parameter CLK_PERIOD = 10;
22
23initial begin
24 rst_n = 0;
25 clk = 0;
26
27 #100;
28 rst_n = 1;
29end
一整天英语
30
31always #(CLK_PERIOD/2) clk = ~clk;
32
33always@(podge clk)
34if(!rst_n)
35begin
36 a = 8'd0;
37 b = 8'd0;
38end
39el
40begin
41 a = a + 1;
42 b = b - 1;
43end
44
45endmodule
ISIM仿真结果:
移位相加乘法器树:
将
assign p_tmp = a_shift0 + a_shift1 + a_shift2 + a_shift3 + a_shift4 + a_shift5 + a_shift6 + a_shift7;换为:
assign sum_01 = a_shift0 + a_shift1;
assign sum_23 = a_shift2 + a_shift3;
assign sum_45 = a_shift4 + a_shift5;
assign sum_67 = a_shift6 + a_shift7;
assign sum_0123 = sum_01 + sum_23;
assign sum_4567 = sum_45 + sum_67;iaea
assign p_tmp = sum_0123 + sum_4567;
就成为乘法器树。
原理是通过切断关键路径,提⾼电路的运⾏频率。
LUT乘法,下⾯的代码利⽤2bit的LUT实现4bit⽆符号数的乘法。
代码:
1module mult_lut(rst_n,
2 clk,
3 a,
4 b,
5 p
6 );
7
8parameter DATA_SIZE = 4;
9
10input rst_n;
11input clk;
12input [DATA_SIZE - 1 : 0] a;
13input [DATA_SIZE - 1 : 0] b;
14
15output [2*DATA_SIZE - 1 : 0] p;
16
17//输⼊数据打⼀个时钟节拍
18reg [DATA_SIZE - 1 : 0] a_r;
19reg [DATA_SIZE - 1 : 0] b_r;
20
21//输⼊数据拆半的乘积
22
23wire [DATA_SIZE - 1 : 0] p_tmp00;
24wire [DATA_SIZE - 1 : 0] p_tmp01;
25
26wire [DATA_SIZE - 1 : 0] p_tmp10;
27wire [DATA_SIZE - 1 : 0] p_tmp11;
28
29//reg [2*DATA_SIZE - 1 : 0] sum01;
30//reg [2*DATA_SIZE - 1 : 0] sum23;
31
32wire [2*DATA_SIZE - 1 : 0] p_tmp;
33reg [2*DATA_SIZE - 1 : 0] p;
34
35//输⼊数据打⼀个时钟节拍
36always@(podge clk)
37if(!rst_n)
38begin
39 a_r <= 4'd0;
40 b_r <= 4'd0;
41end
42el
43begin
44 a_r <= a;
45 b_r <= b;
46end
47
48 mult_lut_2bit u0_mult_lut_2bit (
49 .rst_n(rst_n),
50 .clk(clk),
51 .a(a_r[1:0]),
52 .b(b_r[1:0]),
53 .p(p_tmp00)
54 );
55
56 mult_lut_2bit u1_mult_lut_2bit (
57 .rst_n(rst_n),
58 .clk(clk),
59 .a(a_r[1:0]),
60 .b(b_r[3:2]),
61 .p(p_tmp01)
62 );
63
64 mult_lut_2bit u2_mult_lut_2bit (
65 .rst_n(rst_n),
66 .clk(clk),
67 .a(a_r[3:2]),
68 .b(b_r[1:0]),
69 .p(p_tmp10)
70 );
71
72 mult_lut_2bit u3_mult_lut_2bit (
73 .rst_n(rst_n),
74 .clk(clk),
75 .a(a_r[3:2]),
76 .b(b_r[3:2]),
77 .p(p_tmp11)
78 );
79
80//assign p_tmp = p_tmp00 + p_tmp01<<2 + p_tmp10<<2 + p_tmp11<<4; //不能直接⽤移位操作符实现移位81assign p_tmp = p_tmp00 + {p_tmp01,2'b00} + {p_tmp10,2'b00} + {p_tmp11,4'b00};
82//assign sum01 = p_tmp00 + p_tmp01<<2;
83//assign sum23 = p_tmp10<<2 + p_tmp11<<4;
84
85//assign p_tmp = sum01 + sum23;
86
87always@(podge clk)
88if(!rst_n)
89begin
90 p <= 8'd0;
91end
92el
93begin
94 p <= p_tmp;
95end
96
97endmodule
2bitLUT乘法器:
1module mult_lut_2bit(rst_n,
2 clk,
3 a,
4 b,
5 p
6 );
7
8parameter DATA_SIZE = 2;
effective9
10input rst_n;
11input clk;
12input [DATA_SIZE - 1 : 0] a;
13input [DATA_SIZE - 1 : 0] b;
14
15output [2*DATA_SIZE - 1 : 0] p; 16
17//输⼊数据打⼀个时钟节拍
18reg [DATA_SIZE - 1 : 0] a_r;
19reg [DATA_SIZE - 1 : 0] b_r;
20
21//输出数据打⼀个时钟节拍深大师院国际高中
22reg [2*DATA_SIZE - 1 : 0] p_tmp; 23reg [2*DATA_SIZE - 1 : 0] p;
24
25//输⼊数据打⼀个时钟节拍
26always@(podge clk)
27if(!rst_n)
28begin
29 a_r <= 8'd0;
30 b_r <= 8'd0;
31end
32el
33begin
34 a_r <= a;
35 b_r <= b;
36end
37
38always@(*)
39begin
40ca({a_r,b_r})
414'b0000 : p_tmp = 4'b0000; 424'b0001 : p_tmp = 4'b0000; 434'b0010 : p_tmp = 4'b0000; 444'b0011 : p_tmp = 4'b0000; 454'b0100 : p_tmp = 4'b0000; 464'b0101 : p_tmp = 4'b0001; 474'b0110 : p_tmp = 4'b0010; 484'b0111 : p_tmp = 4'b0011; 49
504'b1000 : p_tmp = 4'b0000; 514'b1001 : p_tmp = 4'b0010; 524'b1010 : p_tmp = 4'b0100; 534'b1011 : p_tmp = 4'b0110; 544'b1100 : p_tmp = 4'b0000; 554'b1101 : p_tmp = 4'b0011; 564'b1110 : p_tmp = 4'b0110; 574'b1111 : p_tmp = 4'b1001; 58endca
59end
60
61always@(podge clk)
62if(!rst_n)
63begin
64 p <= 4'd0;
65end
66el
67begin
68 p <= p_tmp[3:0];
69end日本大学
70
71endmodule