El código incluido aquí toma un flujo de bits de dígitos binarios, el bit menos significativo (LSB) primero, y genera el complemento a dos del flujo completo, también LSB primero. Se adjunta un diagrama de estado de Moore.
Ahora, cuando trato de probar el código en un banco de pruebas, los estados no se actualizan según lo previsto.
El MEV:
El diseño:
module seqDetector( input in,
input clk,
input rst,
output reg out);
//Moore Machine
parameter SX = 3'd4,
S0 = 3'd0,
S1 = 3'd1,
S2 = 3'd2,
S3 = 3'd3;
reg [2:0] cur_state,next_state;
//next state assignment
always @(posedge clk,negedge rst) begin
if( rst == 1'b0)
cur_state <= SX;
else
cur_state <= next_state;
end
//next state calculation
always @(cur_state,in) begin
case(cur_state)
SX: if(in == 1'b0) next_state = S0; else next_state = S1;
S0: if(in == 1'b0) next_state = S0; else next_state = S1;
S1: if(in == 1'b0) next_state = S3; else next_state = S2;
S2: if(in == 1'b0) next_state = S3; else next_state = S2;
S3: if(in == 1'b0) next_state = S3; else next_state = S2;
endcase
end
//output calculation
always @(cur_state) begin
case(cur_state)
SX: out = 1'bx;
S0: out = 1'b0;
S1: out = 1'b1;
S2: out = 1'b0;
S3: out = 1'b1;
endcase
end
endmodule
El banco de pruebas:
`timescale 1ns/1ns
module tb();
initial begin
$dumpfile("2's.vcd");
$dumpvars(0,tb);
end
reg clk;
reg in;
reg rst;
wire out;
initial begin
clk = 1'b1;
forever #5 clk = ~clk;
end
seqDetector s0(in,clk,rst,out);
initial begin
fork
#0 rst = 1'b1;
#10 rst = 1'b0;
#20 rst = 1'b1;
#10 in = 1'b0;
#20 in = 1'b1;
#30 in = 1'b0;
#40 in = 1'b1;
#50 in = 1'b1;
#60 in = 1'b0;
#70 in = 1'b0;
#80 in = 1'b1;
#90 in = 1'b1;
#100 in = 1'b1;
#110 in = 1'bx;
#120 $finish;
join
end
endmodule
El problema se representa en el siguiente gráfico:
Pero cuando cambiamos el banco de pruebas de modo que las entradas se retrasen 1 ns más allá del borde del reloj, el problema existente se resuelve y se logra la funcionalidad. Pero hay algunas fallas cuyo origen no puedo descifrar, como se muestra aquí:
seqDetector s0(in,clk,rst,out);
initial begin
fork
#0 rst = 1'b1;
#10 rst = 1'b0;
#20 rst = 1'b1;
#11 in = 1'b0;
#21 in = 1'b1;
#31 in = 1'b0;
#41 in = 1'b1;
#51 in = 1'b1;
#61 in = 1'b0;
#71 in = 1'b0;
#81 in = 1'b1;
#91 in = 1'b1;
#101 in = 1'b1;
#111 in = 1'bx;
#120 $finish;
join
end
Entonces, la primera pregunta es: ¿por qué hay un problema cuando cambio la entrada en el borde del reloj, desde la perspectiva de escribir un código Verilog?
Y la segunda pregunta es: ¿cuál es la causa de las fallas en la variable next_state?
Usando Mentor Questa 2020.1
y Cadence Xcelium 20.09
no tenemos ningún problema técnico.
Usando Synopsys VCS 2020.03
y Icarus Verilog 14
obtenemos fallas.
Usé EDA Playground para simular, si está interesado, visite este enlace.
La razón por la que tiene fallas son las condiciones de carrera/ peligros de carrera debido al orden no determinista de las declaraciones de bloqueo de Verilog concurrentes en la simulación.
Aquí hay 2 técnicas para evitar fallas en la simulación lógica secuencial:
Aplique el estímulo un poco después del borde activo del reloj, usando un retraso, como lo hizo en su pregunta.
Usando asignaciones sin bloqueo, puede controlar las entradas en el borde activo del reloj sin problemas técnicos.
Este banco de pruebas utiliza asignaciones sin bloqueo y simula sin fallas en estos simuladores: Mentor Questa 2020.1, Cadence Xcelium 20.09, Icarus Verilog 14 y Synopsys VCS 2020.03.
module tb();
initial begin
$dumpfile("dump.vcd");
$dumpvars(0,tb);
end
reg clk;
reg in;
reg rst;
wire out;
initial begin
clk = 1'b1;
forever #5 clk = ~clk;
end
seqDetector s0(in,clk,rst,out);
initial begin
fork
#0 rst <= 1'b1;
#10 rst <= 1'b0;
#20 rst <= 1'b1;
#10 in <= 1'b0;
#20 in <= 1'b1;
#30 in <= 1'b0;
#40 in <= 1'b1;
#50 in <= 1'b1;
#60 in <= 1'b0;
#70 in <= 1'b0;
#80 in <= 1'b1;
#90 in <= 1'b1;
#100 in <= 1'b1;
#110 in <= 1'bx;
#120 $finish;
join
end
endmodule
Registrar las salidas . Para saber más, puedes leer esta respuesta.
usuario253751
holamundo1e.
usuario253751