La simulación de un registro de desplazamiento de 3 etapas utilizando la declaración de asignación de bloqueo en Verilog brinda diferentes resultados de simulación en los simuladores:
El código RTL es el siguiente:
`include "timescale.hv"
module shift_register
#(
parameter DATA_WIDTH = 3
)
(
input wire [(DATA_WIDTH-1):0] din ,
input wire clk ,
input wire rst_n ,
output wire [(DATA_WIDTH-1):0] out
);
reg [(DATA_WIDTH-1):0] q1,q2,q3;
assign out = q3;
always @ (posedge clk or negedge rst_n) begin
if(~rst_n) begin
q1 = {(DATA_WIDTH){1'b0}};
q2 = {(DATA_WIDTH){1'b0}};
q3 = {(DATA_WIDTH){1'b0}};
end else begin
q3 = q2;
q2 = q1;
q1 = din;
end
end
endmodule
El código del banco de pruebas para la simulación del RTL anterior es el siguiente:
`include "timescale.hv"
module tb_shift_register ();
localparam DATA_WIDTH = 4;
reg [(DATA_WIDTH-1):0] din ;
reg clk ;
reg rst_n ;
wire [(DATA_WIDTH-1):0] out ;
shift_register
#(
.DATA_WIDTH(DATA_WIDTH)
)
inst_shift_register
(
.din ( din ),
.clk ( clk ),
.rst_n ( rst_n ),
.out ( out )
);
initial begin
clk = 1'b0;
rst_n = 1'b0;
din = {(DATA_WIDTH){1'b0}};
#20;
rst_n = 1'b1;
end
always #5 clk = ~clk;
always@(posedge clk) begin
if(rst_n) begin
din = 4'd15;
end
end
endmodule
Cuando la simulación funcional se realiza utilizando el TB anterior para el RTL (mencionado anteriormente) en ModelSim, se observa la siguiente forma de onda:
La simulación aparece exactamente igual que la de un registro de desplazamiento de 3 etapas que usa asignación sin bloqueo, donde la salida aparece después de 3 ciclos de reloj y la entrada "din" aparece en "q1" solo en el siguiente ciclo de reloj.
Cuando se realiza la simulación para el mismo RTL y TB utilizando Xilinx Vivado, se observa la siguiente forma de onda:
Se observa que la salida aparece en "q3" después de solo 2 ciclos de reloj y la entrada "din" aparece en "q1" en el mismo ciclo de reloj.
Entonces, tengo 2 preguntas:
Nota: soy consciente del hecho de que la declaración de asignación de bloqueo debe usarse para modelar una lógica combinacional, mientras que una declaración de asignación sin bloqueo debe usarse para modelar una lógica secuencial. Hago esta pregunta porque esta fue una pregunta de la entrevista que me hicieron sobre la implementación de un registro de desplazamiento de 3 etapas usando una declaración de bloqueo.
Usted din
está cambiando al mismo tiempo que el borde del reloj. Esta es una condición de carrera y como tal, el comportamiento del simulador no está definido.
Esto se debe a que usa la asignación de bloqueo aquí:
always@(posedge clk) begin
if(rst_n) begin
din = 4'd15; // << WRONG!
end
end
Cambie eso a una asignación sin bloqueo:
always@(posedge clk) begin
if(rst_n) begin
din <= 4'd15;
end
end
Pero también cambie todas sus otras asignaciones a no bloqueantes: la única razón por la que está funcionando en este momento es accidentalmente porque colocó las asignaciones en el orden q3..q1.
always @ (posedge clk or negedge rst_n) begin
if(~rst_n) begin
q1 <= {(DATA_WIDTH){1'b0}};
q2 <= {(DATA_WIDTH){1'b0}};
q3 <= {(DATA_WIDTH){1'b0}};
end else begin
q3 <= q2;
q2 <= q1;
q1 <= din;
end
end
RAMA KRISHNA MEDA