El código siguiente es tomar el recíproco de un número de punto fijo utilizando el método de Newton. Cuando se afirma start
, la máquina de estado entra en el estado de estimación . Para obtener un punto de partida, comienzo en 1/2 ^ N, donde N es el índice del bit más significativo. Parece que funciona bien en la simulación, pero cuando lo sintetizo aparece la siguiente advertencia:
[Synth 8-5413] Mezcla de control síncrono y asíncrono para el registro abs_n_reg en el módulo qinv. ["/home/chase/vivado-workspace/FixedMath/FixedMath.srcs/sources_1/new/qinv.v":45]
No estoy realmente seguro de por qué recibo esto o cómo solucionarlo. abs_n_reg
es el valor absoluto de n
. Solo estoy configurando su valor a partir de uno de mis bloques siempre.
module qinv(output reg signed [63:0] inv,
output reg ready = 1'b1,
input signed [63:0] n,
input start,
input clk);
reg sign;
reg [63:0] abs_n;
reg [63:0] cur_inv;
reg [63:0] next_inv;
localparam READY = 2'b00,
COMPUTE = 2'b01,
ESTIMATE = 2'b10;
reg [1:0] state = READY;
reg [1:0] next_state = READY;
wire [5:0] mb;
msb m(abs_n, mb);
always @(posedge clk or posedge start) begin
if(start && state == READY) begin
if(n[63] == 1'b1) begin
abs_n <= -n;
sign <= 1'b1;
end else begin
abs_n <= n;
sign <= 1'b0;
end
ready <= 1'b0;
cur_inv <= 64'b0;
state <= ESTIMATE;
end else begin
state <= next_state;
cur_inv <= next_inv;
if(state == COMPUTE && next_state == READY) begin
ready <= 1'b1;
if(sign) inv <= -next_inv;
else inv <= next_inv;
end
end
end
wire [63:0] p1, p2;
qmul m1(p1, abs_n, cur_inv);
reg [63:0] diff;
qmul m2(p2, diff, cur_inv);
always @* begin
next_inv = 0;
next_state = READY;
diff = 0;
if(state == ESTIMATE) begin
next_inv = {1'b1, 63'b0} >> mb;
next_state = COMPUTE;
end else if(state == COMPUTE) begin
diff = {30'b0, 2'b10, 32'b0} - p1;
next_inv = p2;
if(next_inv[63:1] == cur_inv[63:1])
next_state = READY;
else
next_state = COMPUTE;
end
end
endmodule
module msb(input [63:0] n, output reg [5:0] m);
integer i;
always @* begin
m = 0;
for(i = 0; i <= 63; i = i + 1)
if(n[i] == 1'b1) m = i;
end
endmodule
module div_test();
reg clk = 0;
always #5 clk = ~clk;
wire ready;
wire [63:0] out;
reg start = 0;
reg [63:0] in = {8'd207, 24'b0};
qinv d(out, ready, in, start, clk);
initial begin
#5 start = 1;
#10 start = 0;
#1000 $finish;
end
endmodule