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