├── .gitattributes ├── README.md ├── RAM_control.v ├── CSA_carry.v ├── normalization.v ├── multiply_accumulator.v └── unum_CSA.v /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Posit32-2-exact-multiply-accumulator 2 | This is a hardware implementation of exact multiply accumulator for 32-bit Posit number with es=2 (for detail of posit number, see https://posithub.org/docs/Posits4.pdf). 3 | 4 | This project is on Vivado. But it should also work on quartus. 5 | -------------------------------------------------------------------------------- /RAM_control.v: -------------------------------------------------------------------------------- 1 | module RAM_control( 2 | input clk, 3 | input[79:0] data, 4 | input[1:0] wraddress, 5 | input[1:0] rdaddress, 6 | input wren, 7 | 8 | output[79:0] q 9 | ); 10 | 11 | 12 | reg[79:0] dram[3:0]; 13 | initial 14 | begin 15 | dram[0]<=80'h0; 16 | dram[1]<=80'h0; 17 | dram[2]<=80'h0; 18 | dram[3]<=80'h0; 19 | end 20 | 21 | always@(posedge clk)begin 22 | if(wren)begin 23 | dram[wraddress]<=data; 24 | end 25 | end 26 | assign q=dram[rdaddress]; 27 | 28 | endmodule -------------------------------------------------------------------------------- /CSA_carry.v: -------------------------------------------------------------------------------- 1 | module CSA_carry( 2 | input enable, 3 | input clk, 4 | input[79:0] frac_even, 5 | input[79:0] frac_odd, 6 | 7 | 8 | output[1:0] adr_even, 9 | output[1:0] adr_odd, 10 | output[2:0] blk, 11 | output[127:0] frac_out, 12 | output clr_odd, 13 | output sign, 14 | output finish 15 | ); 16 | 17 | reg[15:0] carry; 18 | reg sign_1; 19 | reg[63:0] fraction; 20 | reg[2:0] block,block_delay1; 21 | reg stop_flag,stop_flag_delay1; 22 | reg enable_delay1; 23 | 24 | wire[79:0] frac; 25 | wire[79:0] add_result; 26 | assign frac=block[0]?frac_odd:frac_even; 27 | assign add_result=frac+{{64{carry[15]}},carry}; 28 | always@(posedge clk)begin 29 | if(enable)begin 30 | block<=3'b000; 31 | carry<=16'b0; 32 | fraction<=64'b0; 33 | stop_flag<=1'b0; 34 | end 35 | else begin 36 | if(block==3'b111)begin 37 | stop_flag<=1'b1; 38 | end else begin 39 | block<=block+3'b1; 40 | end 41 | carry<=add_result[79:64]; 42 | fraction<=add_result[63:0]; 43 | end 44 | 45 | if(block==3'b111)begin 46 | sign_1<=carry[15]; 47 | end 48 | 49 | block_delay1<=block; 50 | stop_flag_delay1<=stop_flag; 51 | enable_delay1<=enable; 52 | 53 | end 54 | 55 | reg[127:0] fraction_pos_2,fraction_neg_2; 56 | reg[2:0] block_pos_2,block_neg_2; 57 | reg sign_2; 58 | reg finish_2,finish_2_delay,finish_2_delay2; 59 | always@(posedge clk)begin 60 | if(enable_delay1)begin 61 | fraction_pos_2<=128'b0; 62 | fraction_neg_2<=128'b0; 63 | block_neg_2<=3'b0; 64 | block_pos_2<=3'b0; 65 | end else begin 66 | if(~stop_flag_delay1) begin 67 | if(fraction!=64'b0)begin 68 | fraction_pos_2[127:64]<=fraction; 69 | fraction_pos_2[63:0]<=(block_delay1==(block_pos_2+3'b1))?fraction_pos_2[127:64]:64'b0; 70 | block_pos_2<=block_delay1; 71 | end 72 | 73 | if(fraction!=64'hffff_ffff_ffff_ffff)begin 74 | fraction_neg_2[127:64]<=fraction; 75 | fraction_neg_2[63:0]<=(block_delay1==(block_neg_2+3'b1))?fraction_neg_2[127:64]:64'b0; 76 | block_neg_2<=block_delay1; 77 | end 78 | end 79 | end 80 | 81 | if(block_delay1==3'b110)begin 82 | finish_2<=1'b1; 83 | end 84 | else begin 85 | finish_2<=1'b0; 86 | end 87 | sign_2<=sign_1; 88 | finish_2_delay<=finish_2; 89 | finish_2_delay2<=finish_2_delay; 90 | end 91 | 92 | assign adr_even=block[2:1]; 93 | assign adr_odd=block[2:1]; 94 | assign frac_out=sign_2?fraction_neg_2:fraction_pos_2; 95 | assign blk=sign_2?block_neg_2:block_pos_2; 96 | assign clr_odd=block[0]; 97 | assign sign=sign_2; 98 | assign finish=finish_2_delay2;//&~finish_2_delay2; 99 | 100 | endmodule -------------------------------------------------------------------------------- /normalization.v: -------------------------------------------------------------------------------- 1 | module normalization( 2 | input isInf, 3 | input clk, 4 | input[2:0] blk, 5 | input[127:0] frac_in, 6 | input sign, 7 | input finish_in, 8 | input rst, 9 | 10 | output[31:0] unum, 11 | output isInf_out, 12 | output overflow, 13 | output finish_out 14 | ); 15 | 16 | reg[127:0] frac_1; 17 | reg rst_flag; 18 | reg sign_1; 19 | reg isInf_1; 20 | reg[7:6] expo_value_1; 21 | reg finish_1; 22 | wire[2:0] expo_wire; 23 | assign expo_wire=blk-3'b10; 24 | always@(posedge clk)begin 25 | frac_1<=sign?{~frac_in[127:64]+{63'b0,frac_in[63:0]==64'b0}, ~frac_in[63:0]+64'b1}:frac_in[127:0]; 26 | 27 | expo_value_1[7:6]<=expo_wire[1:0]; 28 | 29 | sign_1<=sign; 30 | 31 | isInf_1<=isInf; 32 | 33 | finish_1<=finish_in; 34 | 35 | end 36 | 37 | reg[7:0] expo_value_2; 38 | reg[31:0] fraction_2; 39 | reg sign_2; 40 | reg isInf_2; 41 | reg overflow_2; 42 | reg finish_2; 43 | wire isZero1,isZero2; 44 | wire[5:0] shift; 45 | wire[127:0] shift_result=frac_1<>>expo_value_2[6:2]; 66 | unumo_3[31]<=sign_2; 67 | overflow_3<=expo_value_2[7]&expo_value_2[6]; 68 | isInf_3<=isInf_2; 69 | finish_3<=finish_2; 70 | end 71 | 72 | reg[31:0] unumo_4; 73 | reg isInf_4; 74 | reg overflow_4; 75 | reg finish_4; 76 | wire[31:0] unumo_2s=unumo_3[31]?{unumo_3[31], ~unumo_3[30:0]+31'b1}:unumo_3; 77 | always@(posedge clk)begin 78 | if(isInf_3)begin unumo_4<=32'h8000_0000; end 79 | else begin unumo_4<=unumo_2s+{31'b0,round}; end 80 | isInf_4<=isInf_3; 81 | overflow_4<=overflow_3; 82 | finish_4<=finish_3; 83 | end 84 | 85 | assign unum=unumo_4; 86 | assign isInf_out=isInf_3; 87 | assign overflow=overflow_4; 88 | assign finish_out=finish_4; 89 | 90 | endmodule 91 | 92 | 93 | module NLC64( 94 | input[63:0] x, 95 | output a, 96 | output[5:0] z 97 | ); 98 | wire[3:0] a1; 99 | wire[15:0] z1; 100 | reg[3:0] z_out; 101 | assign z[3:0]=z_out; 102 | always@(*)begin 103 | case(z[5:4]) 104 | 2'b11:begin z_out<=z1[15:12]; end 105 | 2'b10:begin z_out<=z1[11:8]; end 106 | 2'b01:begin z_out<=z1[7:4]; end 107 | 2'b00:begin z_out<=z1[3:0]; end 108 | endcase 109 | end 110 | 111 | PENC nlc(.x(a1),.a(a),.z(z[5:4])); 112 | 113 | PENC16 PENC16_3(.x(x[15:0]), .a(a1[0]),.z(z1[15:12]) ); 114 | PENC16 PENC16_2(.x(x[31:16]), .a(a1[1]),.z(z1[11:8]) ); 115 | PENC16 PENC16_1(.x(x[47:32]), .a(a1[2]),.z(z1[7:4]) ); 116 | PENC16 PENC16_0(.x(x[63:48]), .a(a1[3]),.z(z1[3:0]) ); 117 | 118 | endmodule 119 | 120 | module PENC16( 121 | input[15:0] x, 122 | output a, 123 | output[3:0] z 124 | ); 125 | wire[3:0] a1; 126 | wire[7:0] z1; 127 | reg[1:0] z_out; 128 | assign z[1:0]=z_out; 129 | always@(*)begin 130 | case(z[3:2]) 131 | 2'b11: begin z_out<=z1[7:6]; end 132 | 2'b10: begin z_out<=z1[5:4]; end 133 | 2'b01: begin z_out<=z1[3:2]; end 134 | 2'b00: begin z_out<=z1[1:0]; end 135 | endcase 136 | end 137 | PENC PENC4(.x(a1[3:0]),.a(a),.z(z[3:2])); 138 | PENC PENC3(.x(x[3:0]),.a(a1[0]),.z(z1[7:6])); 139 | PENC PENC2(.x(x[7:4]),.a(a1[1]),.z(z1[5:4])); 140 | PENC PENC1(.x(x[11:8]),.a(a1[2]),.z(z1[3:2])); 141 | PENC PENC0(.x(x[15:12]),.a(a1[3]),.z(z1[1:0])); 142 | 143 | endmodule 144 | 145 | module PENC( 146 | input[3:0] x, 147 | output a, 148 | output[1:0] z 149 | ); 150 | 151 | assign z[1]=~(x[3]|x[2]); 152 | assign z[0]=~(((~x[2])&x[1])|x[3]); 153 | assign a=(x[0]|x[1]|x[2]|x[3]); 154 | endmodule -------------------------------------------------------------------------------- /multiply_accumulator.v: -------------------------------------------------------------------------------- 1 | module multiply_accumulator( 2 | input clk, 3 | input[31:0] unum1, 4 | input[31:0] unum2, 5 | input finish, 6 | input rst, 7 | input valid, 8 | 9 | output[31:0] sum, 10 | output isInf, 11 | output overflow, 12 | output finish_out 13 | ); 14 | 15 | 16 | ///for csa1 17 | wire[63:0] csa_frac_even; 18 | wire[63:0] csa_frac_odd; 19 | wire[1:0] csa_adr_even; 20 | wire[1:0] csa_adr_odd; 21 | wire csa_finish; 22 | wire csa_finishadr; 23 | wire csa_isInf; 24 | wire csa_sign_even,csa_sign_odd; 25 | wire csa_rst_out; 26 | wire csa_valid_out; 27 | //for carry1 28 | wire[79:0] carry1_frac_even; 29 | wire[79:0] carry1_frac_odd; 30 | wire[1:0] carry1_adr_even; 31 | wire[1:0] carry1_adr_odd; 32 | wire[2:0] carry1_block; 33 | wire[127:0] carry1_frac_out; 34 | wire carry1_clr_odd; 35 | wire carry1_sign; 36 | wire carry1_finish; 37 | /////for ram 38 | wire[79:0] even1_data,even1_q; 39 | wire[1:0] even1_wradr,even1_rdadr; 40 | 41 | wire[79:0] odd1_data,odd1_q; 42 | wire[1:0] odd1_wradr,odd1_rdadr; 43 | wire odd1_enable,even1_enable; 44 | 45 | wire[79:0] even2_data,even2_q; 46 | wire[1:0] even2_wradr,even2_rdadr; 47 | 48 | wire[79:0] odd2_data,odd2_q; 49 | wire[1:0] odd2_wradr,odd2_rdadr; 50 | wire odd2_enable,even2_enable; 51 | ////////// 52 | reg adr_select,carry_select; 53 | reg isInf1,isInf2; 54 | reg[9:0] isInf_delay; 55 | wire carry1_enable; 56 | wire ram_select; 57 | initial 58 | begin 59 | adr_select<=1'b0; 60 | end 61 | always@(posedge clk)begin 62 | if(csa_finishadr||csa_rst_out)begin 63 | adr_select<=~adr_select; 64 | end 65 | end 66 | 67 | //solve infinit case 68 | always@(posedge clk)begin 69 | if(ram_select)begin 70 | isInf1<=1'b0; 71 | isInf2<=isInf2||csa_isInf; 72 | end else 73 | begin 74 | isInf1<=isInf1||csa_isInf; 75 | isInf2<=1'b0; 76 | end 77 | 78 | isInf_delay[9:1]<=isInf_delay[8:0]; 79 | isInf_delay[0]<=ram_select?isInf1:isInf2; 80 | end 81 | 82 | assign carry1_frac_odd=ram_select?odd1_q:odd2_q; 83 | assign carry1_frac_even=ram_select?even1_q:even2_q; 84 | 85 | 86 | assign even1_data=ram_select?80'b0:({{16{csa_sign_even}},csa_frac_even}+even1_q); 87 | assign odd1_data=ram_select?80'b0:({{16{csa_sign_odd}},csa_frac_odd}+odd1_q); 88 | assign even2_data=ram_select?({{16{csa_sign_even}},csa_frac_even}+even2_q):80'b0; 89 | assign odd2_data=ram_select?({{16{csa_sign_odd}},csa_frac_odd}+odd2_q):80'b0; 90 | 91 | assign even1_wradr=ram_select?carry1_adr_even:csa_adr_even; 92 | assign odd1_wradr=ram_select?carry1_adr_odd:csa_adr_odd; 93 | assign even2_wradr=ram_select?csa_adr_even:carry1_adr_even; 94 | assign odd2_wradr=ram_select?csa_adr_odd:carry1_adr_odd; 95 | 96 | assign even1_rdadr=adr_select?carry1_adr_even:csa_adr_even; 97 | assign odd1_rdadr=adr_select?carry1_adr_odd:csa_adr_odd; 98 | assign even2_rdadr=adr_select?csa_adr_even:carry1_adr_even; 99 | assign odd2_rdadr=adr_select?csa_adr_odd:carry1_adr_odd; 100 | 101 | assign odd1_enable=ram_select?carry1_clr_odd:csa_valid_out; 102 | assign odd2_enable=ram_select?csa_valid_out:carry1_clr_odd; 103 | assign even1_enable=ram_select?1'b1:csa_valid_out; 104 | assign even2_enable=ram_select?csa_valid_out:1'b1; 105 | 106 | 107 | assign carry1_enable=csa_finishadr; 108 | assign ram_select=adr_select; 109 | 110 | RAM_control even1( 111 | .clk(clk), 112 | .data(even1_data), 113 | .wraddress(even1_wradr), 114 | .rdaddress(even1_rdadr), 115 | .wren(even1_enable), 116 | .q(even1_q) 117 | ); 118 | 119 | RAM_control odd1( 120 | .clk(clk), 121 | .data(odd1_data), 122 | .wraddress(odd1_wradr), 123 | .rdaddress(odd1_rdadr), 124 | .wren(odd1_enable), 125 | .q(odd1_q) 126 | ); 127 | RAM_control even2( 128 | .clk(clk), 129 | .data(even2_data), 130 | .wraddress(even2_wradr), 131 | .rdaddress(even2_rdadr), 132 | .wren(even2_enable), 133 | .q(even2_q) 134 | ); 135 | RAM_control odd2( 136 | .clk(clk), 137 | .data(odd2_data), 138 | .wraddress(odd2_wradr), 139 | .rdaddress(odd2_rdadr), 140 | .wren(odd2_enable), 141 | .q(odd2_q) 142 | ); 143 | 144 | CSA_carry carry1( 145 | .clk(clk), 146 | .enable(carry1_enable), 147 | .frac_even(carry1_frac_even), 148 | .frac_odd(carry1_frac_odd), 149 | 150 | .adr_even(carry1_adr_even), 151 | .adr_odd(carry1_adr_odd), 152 | .blk(carry1_block), 153 | .frac_out(carry1_frac_out), 154 | .clr_odd(carry1_clr_odd), 155 | .sign(carry1_sign), 156 | .finish(carry1_finish) 157 | ); 158 | 159 | 160 | unum_CSA unum_csa1( 161 | .clk(clk), 162 | .unum1(unum1), 163 | .unum2(unum2), 164 | .finish_in(finish), 165 | .rst(rst), 166 | .valid(valid), 167 | 168 | .frac_even(csa_frac_even), 169 | .frac_odd(csa_frac_odd), 170 | .adr_even(csa_adr_even), 171 | .adr_odd(csa_adr_odd), 172 | .finish_o(csa_finish), 173 | .finish_adr(csa_finishadr), 174 | .isInf(csa_isInf), 175 | .sign_even(csa_sign_even), 176 | .sign_odd(csa_sign_odd), 177 | .rst_out(csa_rst_out), 178 | .valid_out(csa_valid_out) 179 | ); 180 | 181 | 182 | normalization normal1( 183 | .isInf(isInf_delay[9]), 184 | .clk(clk), 185 | .blk(carry1_block), 186 | .frac_in(carry1_frac_out), 187 | .sign(carry1_sign), 188 | .finish_in(carry1_finish), 189 | .rst(rst), 190 | 191 | .unum(sum), 192 | .isInf_out(isInf), 193 | .overflow(overflow), 194 | .finish_out(finish_out) 195 | ); 196 | 197 | 198 | endmodule -------------------------------------------------------------------------------- /unum_CSA.v: -------------------------------------------------------------------------------- 1 | module unum_CSA( 2 | input clk, 3 | input[31:0] unum1, 4 | input[31:0] unum2, 5 | input finish_in, 6 | input rst, 7 | input valid, 8 | 9 | output[63:0] frac_even, 10 | output[63:0] frac_odd, 11 | output[1:0] adr_even, 12 | output[1:0] adr_odd, 13 | output finish_adr, 14 | output finish_o, 15 | output isInf, 16 | output sign_even, 17 | output sign_odd, 18 | output rst_out, 19 | output valid_out 20 | ); 21 | 22 | reg[31:0] unum1_0,unum2_0; 23 | reg finish_0,rst_0,valid_0; 24 | //0st in order to reduce the delay, first buffer all the input 25 | always@(posedge clk)begin 26 | unum1_0<=unum1; 27 | unum2_0<=unum2; 28 | finish_0<=finish_in; 29 | rst_0<=rst; 30 | valid_0<=valid; 31 | end 32 | 33 | 34 | //1st: check whether the input number is special situations: zero and Inf 35 | //If the number is nagative, change it from 2's complement to original 36 | reg[1:0] isZero_1; //isZero[1]: unum1 [0]: unum2 =0 if value is zero 37 | reg[1:0] isInf_1; //isInf[1]: unum1 [0]: unum2 =1 if value is Inf 38 | reg[31:0] temp1,temp2; //store changed or unchange input numbers 39 | //reg[4:0] unum1_shift,unum2_shift; //result of zero/one counting 40 | reg finish_1; 41 | reg rst_1; 42 | reg valid_1; 43 | wire[4:0] n1,n2;//result of leading zero count 44 | wire[30:0] unum1_2s,unum2_2s; 45 | assign unum1_2s=unum1_0[31]?(~unum1_0[30:0]+31'b1):unum1_0[30:0]; 46 | assign unum2_2s=unum2_0[31]?(~unum2_0[30:0]+31'b1):unum2_0[30:0]; 47 | always@(posedge clk)begin 48 | if(unum1_0[30:0]==31'b0)begin isZero_1[1]<=unum1_0[31]; isInf_1[1]<=unum1_0[31]; end 49 | else begin isZero_1[1]<=1'b1; isInf_1[1]<=1'b0;end 50 | 51 | if(unum2_0[30:0]==31'b0)begin isZero_1[0]<=unum2_0[31]; isInf_1[0]<=unum2_0[31]; end 52 | else begin isZero_1[0]<=1'b1; isInf_1[0]<=1'b0; end 53 | 54 | temp1<=unum1_2s; /// change unum from 2nd complement to original 55 | 56 | temp2<=unum2_2s; 57 | 58 | finish_1<=finish_0; 59 | valid_1<=valid_0; 60 | 61 | temp1[31]<=unum1_0[31]; 62 | temp2[31]<=unum2_0[31]; 63 | 64 | rst_1<=rst_0; 65 | end 66 | 67 | 68 | //2nd: Left shift the temp so that the exponent bits, sign bit and fraction bits will in the certain positions. 69 | //change regime bits and exponent bits into exponent value in 2's complement format 70 | reg isInf_2; //if one of the input numbers is Inf, this bit will be 1 71 | reg[31:0] temp1_2,temp2_2; //[31]:sign bit [30]: ==1 if component value is negative, ==0 if zero or positive. [29]: ~[30] [28:26]:exponent bits [25:0]:fraction bit 72 | reg[7:2] expo_num1, expo_num2; //store exponent values 73 | reg NaN_2; 74 | reg rst_2; 75 | reg isZero_2; 76 | reg finish_2; 77 | reg valid_2; 78 | always@(posedge clk)begin ///2nd 79 | temp1_2[30:0]<=temp1[30:0]<