安德鲁

[笔记].算法 - 乘积累加器.[Verilog]

0
阅读(4874)

出自Quartus II自带模板。

1. 无符号数乘积累加器

01 module unsigned_multiply_accumulate
02 #(parameter WIDTH=8)
03 (
04   input clk, aclr, clken, sload,
05   input [WIDTH-1:0] dataa,
06   input [WIDTH-1:0] datab,
07   output reg [2*WIDTH-1:0] adder_out
08 );
09  
10   // Declare registers and wires
11   reg  [WIDTH-1:0] dataa_reg, datab_reg;
12   reg  sload_reg;
13   reg   [2*WIDTH-1:0] old_result;
14   wire [2*WIDTH-1:0] multa;
15  
16   // Store the results of the operations on the current data
17   assign multa = dataa_reg * datab_reg;
18  
19   // Store the value of the accumulation (or clear it)
20   always @ (adder_out, sload_reg)
21   begin
22     if (sload_reg)
23       old_result <= 0;
24     else
25       old_result <= adder_out;
26   end
27  
28   // Clear or update data, as appropriate
29   always @ (posedge clk or posedge aclr)
30   begin
31     if (aclr)
32     begin
33       dataa_reg <= 0;
34       datab_reg <= 0;
35       sload_reg <= 0;
36       adder_out <= 0;
37     end
38     else if (clken)
39     begin
40       dataa_reg <= dataa;
41       datab_reg <= datab;
42       sload_reg <= sload;
43       adder_out <= old_result + multa;
44     end
45   end
46 endmodule

2. 有符号数乘积累加器

01 module signed_multiply_accumulate
02 #(parameter WIDTH=8)
03 (
04   input clk, aclr, clken, sload,
05   input signed [WIDTH-1:0] dataa,
06   input signed [WIDTH-1:0] datab,
07   output reg signed [2*WIDTH-1:0] adder_out
08 );
09  
10   // Declare registers and wires
11   reg  signed [WIDTH-1:0] dataa_reg, datab_reg;
12   reg  sload_reg;
13   reg   signed [2*WIDTH-1:0] old_result;
14   wire signed [2*WIDTH-1:0] multa;
15  
16   // Store the results of the operations on the current data
17   assign multa = dataa_reg * datab_reg;
18  
19   // Store (or clear) old results
20   always @ (adder_out, sload_reg)
21   begin
22     if (sload_reg)
23       old_result <= 0;
24     else
25       old_result <= adder_out;
26   end
27  
28   // Clear or update data, as appropriate
29   always @ (posedge clk or posedge aclr)
30   begin
31     if (aclr)
32     begin
33       dataa_reg <= 0;
34       datab_reg <= 0;
35       sload_reg <= 0;
36       adder_out <= 0;
37     end
38     else if (clken)
39     begin
40       dataa_reg <= dataa;
41       datab_reg <= datab;
42       sload_reg <= sload;
43       adder_out <= old_result + multa;
44     end
45   end
46 endmodule

3. 四乘积累加器

01 module sum_of_four_multiply_accumulate
02 #(parameter INPUT_WIDTH=18, parameter OUTPUT_WIDTH=44)
03 (
04   input clk, ena,
05   input [INPUT_WIDTH-1:0] dataa, datab, datac, datad,
06   input [INPUT_WIDTH-1:0] datae, dataf, datag, datah,
07   output reg [OUTPUT_WIDTH-1:0] dataout
08 );
09  
10   // Each product can be up to 2*INPUT_WIDTH bits wide.
11   // The sum of four of these products can be up to 2 bits wider.
12   wire [2*INPUT_WIDTH+1:0] mult_sum;
13  
14   // Store the results of the operations on the current inputs
15   assign mult_sum = (dataa * datab + datac * datad) + (datae * dataf + datag * datah);
16  
17   // Store the value of the accumulation
18   always @ (posedge clk)
19   begin
20     if (ena == 1)
21     begin
22               dataout <= dataout + mult_sum;
23     end
24   end
25 endmodule

4. 带异步复位的四乘积累加器

01 module sum_of_four_multiply_accumulate_with_asynchronous_reset
02 #(parameter INPUT_WIDTH=18, parameter OUTPUT_WIDTH=44)
03 (
04   input clk, ena, aclr,
05   input [INPUT_WIDTH-1:0] dataa, datab, datac, datad,
06   input [INPUT_WIDTH-1:0] datae, dataf, datag, datah,
07   output reg [OUTPUT_WIDTH-1:0] dataout
08 );
09  
10   // Each product can be up to 2*INPUT_WIDTH bits wide.
11   // The sum of four of these products can be up to 2 bits wider.
12   wire [2*INPUT_WIDTH+1:0] mult_sum;
13  
14   // Store the results of the operations on the current inputs
15   assign mult_sum = (dataa * datab + datac * datad) + (datae * dataf + datag * datah);
16  
17   // Store the value of the accumulation
18   always @ (posedge clk)
19   begin
20     if (ena == 1)
21     begin
22               dataout <= ((aclr == 1) ? 0 : dataout) + mult_sum;
23     end
24   end
25 endmodule