The synthesis I'm trying to do is on a GCD algorithm Finite State Machine that works using the "subtract if bigger" method. I will attach the code and try and formulate a decent question.
module GCD_R (A,B,out,nrst,act,clk,fla_g);
input [31:0] A, B;
input clk, act, nrst;
output reg fla_g;
output reg [31:0] out;
reg [3:0] state, next_state;
reg [31:0] A_reg, B_reg, Aint_reg, Bint_reg, out_reg;//2 registers will keep intermediate numbers+out, and next numbers
parameter IDLE = 3'b001;
parameter ABIG = 3'b010;
parameter BBIG = 3'b100;
reg next_flag;
always @(*)
case (state)
IDLE: begin
$display("start");
if(act == 0) begin
A_reg = A; //A,B are wires that contain numbers from an external source
B_reg = B; //first assign to A_reg and B_reg
out_reg = 31'bx;
next_flag = 1'b0;
next_state = IDLE;
end
if(act == 1)
if(A_reg==0) begin
out_reg = B_reg;
next_flag = 1'b1; //testbench will know when we stopped
Aint_reg = A_reg; //taking care not to infer latches
Bint_reg = B_reg;
next_state = IDLE;
end
else if (B_reg==0) begin
out_reg = A_reg;
next_flag = 1'b1;
Aint_reg = A_reg; //taking care not to infer latches
Bint_reg = B_reg;
next_state = IDLE;
end
else if (A_reg >= B_reg) begin
out_reg = 31'bx;
next_flag = 1'b0;
Aint_reg = A_reg;
Bint_reg = B_reg;
next_state = ABIG;
end
else begin
out_reg = 4'bxxx;
next_flag = 1'b0;
Aint_reg = A_reg;
Bint_reg = B_reg;
next_state = BBIG;
end
else
begin
Aint_reg = A_reg;
Bint_reg = B_reg;
out_reg = 4'bxxx;
next_flag = 1'b0;
next_state = 4'bx;
end
end
ABIG: begin
if (A_reg==0 | B_reg==0) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = IDLE;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else if (B_reg > A_reg) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = BBIG;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = ABIG;
Aint_reg = A_reg - B_reg;
Bint_reg = B_reg;
end
end
BBIG: begin
if (A_reg==0 | B_reg==0) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = IDLE;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else if (A_reg > B_reg) begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = ABIG;
Aint_reg = A_reg;
Bint_reg = B_reg;
end
else begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = BBIG;
Aint_reg = A_reg;
Bint_reg = B_reg - A_reg;
end
end
default: begin
out_reg = 31'bx;
next_flag = 1'b0;
next_state = 4'bx;
Aint_reg = A_reg;
Bint_reg = B_reg;
$display("%t: State machine not initialized/n",$time);
end
endcase
always @(posedge clk or negedge nrst)
if (~nrst) begin
state <= IDLE;//we get the new values by resetting first
out <= 4'bx;//we don't want anything there at the reset
fla_g <= 1'b0;
end
else begin
state <= next_state;//otherwise, get the next state and the next registers to the intermediate ones
A_reg <= Aint_reg;// 2nd assign to A_reg and B_reg- that's the problem
B_reg <= Bint_reg;
out <= out_reg;
fla_g <= next_flag;
end
endmodule
first, A and B are wires that will receive a list of numbers to compare via external source(some textfile in a testbench).
A_reg and B_reg are the intermediate registers that keep the numbers that we are checking the "if" statements on,
Aint_reg and Bint_reg are registers that keep the intermediate values of registers after the operations only to send them back to A_reg and B_reg when the clock is rising,
act decides whether the machine is on "on" mode and can perform the algorithm
nrst is the negative reset toggle
how was the problem formed:
you can see that at the beginning, there is an if(act == 0)
condition. It was put there to ensure that the values at the A,B wires(received externally) will enter the registers there, instead of entering them in the sequential block while we were on the if(~nrst)
condition since it made no sense entering a dynamic value while in reset.
This takes us to the current problem- I know that assigning a value to A and B both in the sequential and combinatoric blocks is what creates the problem, but I just can't find an alternative.
p.s. the fact that I'm using A_reg = A
creates latches since I don't assign to A_reg
anywhere else, and that's another problem since writing
Aint_reg = A_reg;
A_reg = Aint_reg;
to satisfy latches doesn't sit right with me.
p.s.2. I tried looking into the similar questions on the site, but owing to my lack of enough knowledge on the subject I couldn't relate my problem to the ones out there
I'll be glad to receive any help, thanks
EDIT: I deleted the nonblocking assignments in the if(~nrst) sequential block so as to not to multiple assign A_reg <= 0
there and A_reg = A
in the combinatoric block, but the multiple assignment problem still bugs it somehow
EDIT2: seems that I forgot a fundamental thing- don't assign to the same variable in two different "always" block, but I just can't think of a good enough solution to assign the wires A,B to a register and not assign to it again in the sequential block