Back to posts Edit this post
Copy content

22 May 12:49

cozag
module complex_mul ( input wire CLK, input wire RST, input wire I_STB, input wire [31:0] I_ARE, input wire [31:0] I_AIM, input wire [31:0] I_BRE, input wire [31:0] I_BIM, output reg O_STB, output reg [31:0] O_CRE, output reg [31:0] O_CIM ); // Stany FSM do kontroli sekwencji operacji mnożenia i dodawania localparam IDLE = 0, MUL1 = 1, MUL2 = 2, MUL3 = 3, MUL4 = 4, ADD1 = 5, ADD2 = 6, DONE = 7; reg [2:0] state, next_state; // Wartości pośrednie reg [31:0] a, b, c, d; reg [31:0] mult_a, mult_b; wire mult_stb; wire [63:0] mult_result; // bo multiplier daje szerokość sumy A_WIDTH+B_WIDTH wire add_stb; wire [31:0] add_result; // Flagi potwierdzenia handshake reg mult_ack, add_ack; // Instancje modułów mnożenia i dodawania // Zakładam, że multiplier i adder mają I_STB/I_ACK handshake, wynik i flagi multiplier #(.A_WIDTH(32), .B_WIDTH(32)) mul_inst ( .CLK(CLK), .RST(RST), .I_STB(mult_stb), .I_ACK(mult_ack), .I_DAT_A(mult_a), .I_DAT_B(mult_b), .O_STB(), .O_DAT(mult_result), .O_ACK(1'b1) // zakładam, że odbiorca zawsze gotowy ); adder #(.A_WIDTH(32), .B_WIDTH(32)) add_inst ( .CLK(CLK), .RST(RST), .I_STB(add_stb), .I_ACK(add_ack), .I_DAT_A(a), .I_DAT_B(b), .O_STB(), .O_DAT(add_result), .O_ACK(1'b1) ); // Rejestry do wyników mnożeń (32 bitów, bierzemy dolne 32 bity wyniku 64 bitowego mnożenia) reg [31:0] mul_ac, mul_bd, mul_ad, mul_bc; assign mult_stb = (state == MUL1) || (state == MUL2) || (state == MUL3) || (state == MUL4); assign add_stb = (state == ADD1) || (state == ADD2); always @(posedge CLK or posedge RST) begin if (RST) begin state <= IDLE; O_STB <= 0; O_CRE <= 0; O_CIM <= 0; mult_ack <= 0; add_ack <= 0; end else begin state <= next_state; case (state) IDLE: begin O_STB <= 0; if (I_STB) begin // startujemy obliczenia a <= 0; b <= 0; c <= 0; d <= 0; end mult_ack <= 0; add_ack <= 0; end MUL1: begin mult_a <= I_ARE; mult_b <= I_BRE; mult_ack <= 1; end MUL2: begin mult_a <= I_AIM; mult_b <= I_BIM; mult_ack <= 1; end MUL3: begin mult_a <= I_ARE; mult_b <= I_BIM; mult_ack <= 1; end MUL4: begin mult_a <= I_AIM; mult_b <= I_BRE; mult_ack <= 1; end ADD1: begin // dodawanie wyników MUL1 i MUL2 (mul_ac i mul_bd) a <= mul_ac; b <= mul_bd; add_ack <= 1; end ADD2: begin // odejmowanie (mul_ad i mul_bc) => a - b // tutaj trzeba zmienić na odejmowanie, więc podamy a = mul_ad, b = mul_bc i zrobimy dodanie z dopełnieniem do 2 a <= mul_ad; b <= (~mul_bc) + 1; // dopełnienie do 2 = -b add_ack <= 1; end DONE: begin O_CRE <= add_result; // wynik z ADD1 O_CIM <= add_result; // wynik z ADD2 O_STB <= 1; mult_ack <= 0; add_ack <= 0; end endcase end end // Logika przejścia stanów (prosta wersja, w prawdziwym projekcie warto synchronizować handshaki) always @(*) begin next_state = state; case (state) IDLE: if (I_STB) next_state = MUL1; MUL1: next_state = MUL2; MUL2: next_state = MUL3; MUL3: next_state = MUL4; MUL4: next_state = ADD1; ADD1: next_state = ADD2; ADD2: next_state = DONE; DONE: if (!I_STB) next_state = IDLE; endcase end // Zapisywanie wyników mnożeń do rejestrów always @(posedge CLK) begin if (state == MUL1) mul_ac <= mult_result[31:0]; else if (state == MUL2) mul_bd <= mult_result[31:0]; else if (state == MUL3) mul_ad <= mult_result[31:0]; else if (state == MUL4) mul_bc <= mult_result[31:0]; end endmodule

No files