Back to posts Edit this post
Copy content

22 May 12:55

ggfg
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 typedef enum reg [2:0] { IDLE, MUL1, // mnożenie I_ARE * I_BRE i I_AIM * I_BIM SUB, // odejmowanie (MUL1_res1 - MUL1_res2) MUL2, // mnożenie I_AIM * I_BRE i I_ARE * I_BIM ADD, // dodawanie (MUL2_res1 + MUL2_res2) DONE } state_t; state_t state, next_state; // Sygnaly mnożenia i dodawania reg mul_stb_1, mul_stb_2; wire mul_ack_1, mul_ack_2; wire [63:0] mul_out_1, mul_out_2; // wynik mnożenia 64-bit reg adder_stb; wire adder_ack; wire [32:0] adder_out; // suma/roznica 33-bit z addersa // Dane wejściowe do mnożarek i addersów reg [31:0] mul1_a1, mul1_b1, mul1_a2, mul1_b2; reg [31:0] mul2_a1, mul2_b1, mul2_a2, mul2_b2; reg [63:0] mul1_res1, mul1_res2; reg [63:0] mul2_res1, mul2_res2; reg [63:0] adder_in_a, adder_in_b; // Trzeba zmieścić wynik 64-bit na 32-bit wyjściowe // uproszczenie: bierzemy tylko niższe 32-bit (nie uwzględniamy overflow) // --- Instancje modułów --- multiplier #(.A_WIDTH(32), .B_WIDTH(32)) mul1 ( .RST(RST), .CLK(CLK), .I_STB(mul_stb_1), .I_ACK(mul_ack_1), .I_DAT_A(mul1_a1), .I_DAT_B(mul1_b1), .O_STB(), .O_DAT(mul_out_1[31:0]), .O_ACK(1'b1) // zakładamy natychmiastowy odbiór wyniku (można zmodyfikować) ); multiplier #(.A_WIDTH(32), .B_WIDTH(32)) mul2 ( .RST(RST), .CLK(CLK), .I_STB(mul_stb_2), .I_ACK(mul_ack_2), .I_DAT_A(mul1_a2), .I_DAT_B(mul1_b2), .O_STB(), .O_DAT(mul_out_2[31:0]), .O_ACK(1'b1) ); // Adder do sumy i różnicy adder #(.A_WIDTH(32), .B_WIDTH(32)) add ( .RST(RST), .CLK(CLK), .I_STB(adder_stb), .I_ACK(adder_ack), .I_DAT_A(adder_in_a[31:0]), .I_DAT_B(adder_in_b[31:0]), .O_STB(), .O_DAT(adder_out[31:0]), .O_ACK(1'b1) ); // FSM logic always @(posedge CLK or posedge RST) begin if (RST) begin state <= IDLE; O_STB <= 0; O_CRE <= 0; O_CIM <= 0; mul_stb_1 <= 0; mul_stb_2 <= 0; adder_stb <= 0; end else begin state <= next_state; case (state) IDLE: begin O_STB <= 0; if (I_STB) begin // Start pierwszych dwóch mnożeń mul_stb_1 <= 1; mul_stb_2 <= 1; mul1_a1 <= I_ARE; mul1_b1 <= I_BRE; mul1_a2 <= I_AIM; mul1_b2 <= I_BIM; end else begin mul_stb_1 <= 0; mul_stb_2 <= 0; end end MUL1: begin // Czekamy na zakończenie mnożeń mul_stb_1 <= 0; mul_stb_2 <= 0; // Załóżmy, że mnożenia są gotowe natychmiast po cyklu (bo I_ACK i O_ACK logiczne) // Zapisujemy wyniki mul1_res1 <= {32'b0, mul_out_1[31:0]}; mul1_res2 <= {32'b0, mul_out_2[31:0]}; // Start odejmowania: mul1_res1 - mul1_res2 adder_stb <= 1; adder_in_a <= {32'b0, mul_out_1[31:0]}; adder_in_b <= ~{32'b0, mul_out_2[31:0]} + 1; // do odejmowania: a + (~b + 1) end SUB: begin adder_stb <= 0; O_CRE <= adder_out[31:0]; // Teraz kolejne mnożenia dla części urojonej mul_stb_1 <= 1; mul_stb_2 <= 1; mul1_a1 <= I_AIM; mul1_b1 <= I_BRE; mul1_a2 <= I_ARE; mul1_b2 <= I_BIM; end MUL2: begin mul_stb_1 <= 0; mul_stb_2 <= 0; mul2_res1 <= {32'b0, mul_out_1[31:0]}; mul2_res2 <= {32'b0, mul_out_2[31:0]}; // Dodawanie wyników adder_stb <= 1; adder_in_a <= {32'b0, mul_out_1[31:0]}; adder_in_b <= {32'b0, mul_out_2[31:0]}; end ADD: begin adder_stb <= 0; O_CIM <= adder_out[31:0]; O_STB <= 1; end DONE: begin if (!I_STB) O_STB <= 0; end endcase end end // Next state logic always @(*) begin case(state) IDLE: next_state = I_STB ? MUL1 : IDLE; MUL1: next_state = SUB; SUB: next_state = MUL2; MUL2: next_state = ADD; ADD: next_state = DONE; DONE: next_state = I_STB ? DONE : IDLE; default: next_state = IDLE; endcase end endmodule

No files