Estoy codificando un mux de 32 vías en verilog.
La entrada es un contador que cuenta de 0 a 31, incrementando cada ciclo de reloj. Cada valor de contador selecciona una porción diferente de un vector como salida.
En mi proceso de máquina de estado, el contador se genera de la siguiente manera:
// Complicated stuff!
if (counter < C_NUM_CYCLES-1) begin
counter <= counter + 1;
end
Utilizando el recuento, selecciono un segmento de 32 bits de un vector de 1024 bits. La entrada 0 selecciona los 32 bits LS del vector, 1 selecciona los siguientes 32 y así sucesivamente. Esta porción se genera en un proceso cronometrado separado:
S1_input_val <= 1;
S1_input <= input_vector_i[(counter_z[0]+1)*(C_S1_INPUT_LENGTH)-1 -: C_S1_INPUT_LENGTH];
Esta señal de 32 bits se usa en otra entidad que deseo usar para procesar el número completo de 1024 bits, un segmento de 32 bits a la vez.
Funciona perfectamente bien en simulación. La implementación produce un horrible informe de tiempos:
Delay Cumulitive
CARRY4 (Prop_carry4_CI_CO[3]) (r) 0.117 6.879 Site: SLICE_X54Y3 counter_reg[12]_i_1/CO[3]
CARRY4 (Prop_carry4_CI_CO[3]) (r) 0.117 6.996 Site: SLICE_X54Y4 counter_reg[16]_i_1/CO[3]
...
CARRY4 (Prop_carry4_CI_CO[3]) (r) 0.114 39.719 Site: SLICE_X55Y148 counter_reg[1016]_i_1/CO[3]
CARRY4 (Prop_carry4_CI_O[1]) (r) 0.334 40.053 Site: SLICE_X55Y149 counter_reg[1020]_i_1/CO[3]
Arrival Time 40.053 <- ns!
Este problema permanece incluso después de agregar varias etapas de registro y todo se está ejecutando en procesos cronometrados. Parece que solo el mecanismo de selección de mux generado por las herramientas está causando esto. No sé cómo puedo ingresar para agregar etapas de registro.
¿Esto es solo una limitación inherente del hardware, o hay un problema con mi mux y la forma en que lo estoy implementando? puedo hacerlo mejor? ¿Cómo puedo mejorar el tiempo?
Una de las cosas más importantes que me desconcierta es cuál es la señal a la que se hace referencia como counter_reg
en el informe de temporización. Sube a 1024, mientras que el contador real solo sube a 32. He pasado un tiempo investigando en el editor de FPGA pero no he tenido mucho éxito.
La herramienta es Vivado 2014.1.
Editar:
Pensé que tal vez las señales que iban a la siguiente entidad no se estaban registrando lo antes posible. Ese no es el caso, este es el código en el extremo receptor de las entradas:
// Register in inputs
always@(posedge clk) begin
if(rst) begin
vector_i <= 0;
vector_val_i <= 0;
end
else begin
if (input_vector_val == 1) begin
vector_i <= input_vector;
vector_val_i <= input_vector_val;
end
else begin
vector_i <= 0;
vector_val_i <= 0;
end
end
end
Todos los códigos relevantes:
parameter C_S1_INPUT_LENGTH = 32,
parameter C_NUM_CYCLES_BITS = 5
...
reg [C_NUM_CYCLES_BITS-1:0] counter;
reg [C_NUM_CYCLES_BITS-1:0] counter_z [3:0];
reg [C_NUM_STATES-1:0] current_state;
reg [C_S1_INPUT_LENGTH-1:0] S1_input;
reg S1_input_val;
...
// Latch in inputs
always@(posedge clk) begin
if(rst) begin
current_state <= S_IDLE;
counter <= 0;
input_vector_i <= 0;
S2_input_val <= 0;
end
else begin
case (current_state)
S_IDLE:
begin
counter <= 0;
S2_input_val <= 0;
if (input_vector_val == 1)
begin
current_state <= S_STAGE_ONE;
input_vector_i <= input_vector;
end
else
current_state <= S_IDLE;
end
S_STAGE_ONE:
begin
S2_input_val <= 0;
if (counter < C_NUM_CYCLES-1) begin
counter <= counter + 1;
end
if (S1_valid == ones)
begin
current_state <= S_STAGE_TWO;
S2_input_val <= 1;
end
else
current_state <= S_STAGE_ONE;
end
S_STAGE_TWO:
// not relevant
default:
$display("wrong state!");
endcase;
end
end // always@ (posedge clk)
always@(posedge clk) begin
if(rst) begin
S1_input_val <= 0;
S1_input <= 0;
end
else begin
if (current_state == S_STAGE_ONE) begin
S1_input_val <= 1;
S1_input <= input_vector_i[(counter_z[0]+1)*(C_S1_INPUT_LENGTH)-1 -: C_S1_INPUT_LENGTH];
end
else begin
S1_input <= 0;
S1_input_val <= 0;
end
end
end
always@(posedge clk) begin
counter_z[0] <= counter;
counter_z[1] <= counter_z[0];
counter_z[2] <= counter_z[1];
counter_z[3] <= counter_z[2];
end