Estoy intentando implementar un bloqueo de combinación síncrono que se desbloqueará una vez que reciba "101011" usando verilog. Tiene una entrada: x, y tres salidas: desbloqueo, listo y error. Siguiendo estas reglas:
- En estado inicial listo = 1. Permanece en inicial mientras que x = 0
- Al recibir 101011 en x, desbloquear = 1. Permanece en desbloqueo mientras x = 1
- Si está en estado de desbloqueo y x = 0, irá al estado inicial
- En todos los estados que no sean inicial y desbloqueo, si la entrada en x no avanza la secuencia (101011), error = 1.
- Permanecer en estado de error mientras que x = 1. Si x = 0 en estado de error, vaya al estado inicial
A partir de estas reglas, creé el diagrama de estado a continuación (etiqueté el estado inicial s_reset, ya que la inicial es 000000): Lohetratadocomoundetectordesecuenciasyacabodecrearunmontóndeestados.Aquíestámicódigoacontinuación:
modulelock(inputwireclock,inputwirereset,inputwirex,outputregready,outputregunlock,outputregerror);reg[2:0]state;reg[2:0]next_state;localparams_reset=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100,s5=3'b101,open=3'b110,s_error=3'b111;s_error=3'b111;always@(posedgeclock,posedgereset)beginif(reset)state<=s_reset;elsestate<=next_state;endalways@*begincase(state)s_reset:if(x==1'b1)beginnext_state=s1;unlock=1'b0;ready=1'b0;error=1'b0;endelsebeginnext_state=s_reset;unlock=1'b0;ready=1'b1;error=1'b0;ends1:if(x==1'b0)beginnext_state=s2;unlock=1'b0;ready=1'b0;error=1'b0;endelsebeginnext_state=s_error;unlock=1'b0;ready=1'b0;error=1'b1;ends2:if(x==1'b1)beginnext_state=s3;unlock=1'b0;ready=1'b0;error=1'b0;endelsebeginnext_state=s_error;unlock=1'b0;ready=1'b0;error=1'b1;ends3:if(x==1'b0)beginnext_state=s4;unlock=1'b0;ready=1'b0;error=1'b0;endelsebeginnext_state=s_error;unlock=1'b0;ready=1'b0;error=1'b1;ends4:if(x==1'b1)beginnext_state=s5;unlock=1'b0;ready=1'b0;error=1'b0;endelsebeginnext_state=s_error;unlock=1'b0;ready=1'b0;error=1'b1;ends5:if(x==1'b1)beginnext_state=open;unlock=1'b0;ready=1'b0;error=1'b0;endelsebeginnext_state=s_error;unlock=1'b0;ready=1'b0;error=1'b1;endopen:if(x==1'b0)beginnext_state=s_reset;unlock=1'b1;ready=1'b0;error=1'b0;endelsebeginnext_state=open;unlock=1'b1;ready=1'b0;error=1'b0;ends_error:if(x==1'b0)beginnext_state=s_reset;unlock=1'b0;ready=1'b1;error=1'b0;endelsebeginnext_state=s_error;unlock=1'b0;ready=1'b0;error=1'b1;enddefault:beginnext_state=s_reset;unlock=1'b0;ready=1'b1;error=1'b0;endendcaseendendmodule
Testbenchacontinuación
moduletestbench;regclock;//Freerunningclockregreset;//Resetactivehighregx;//Input-Xwireready;//Output-readyforcombinationwireunlock;//Output-unlockedwireerror;//Output-errorincombinationinitialbegin$dumpfile("dump.vcd" );
$dumpvars;
clock = 0; // Set initial values for inputs
reset = 0;
x = 0;
#1 reset = 1;
#9 reset = 0;
#30 // Wait to make sure system is idle
// Test good sequence
x = 1;
#10 x = 0;
#10 x = 1;
#10 x = 0;
#10 x = 1;
#10 x = 1;
// Test to see if stays unlocked and then returns to ready
#30 x = 0;
// Test 1011 which should go into error on the fourth digit
#30 x = 1;
#10 x = 0;
#10 x = 1;
#10 x = 1;
// Stay in error until x -> 0
#30 x = 0;
// Wait in ready and test error on a zero
#30 x = 1;
#10 x = 0;
#10 x = 1;
#10 x = 0;
#30 $finish;
end
always
#5 clock = ~clock;
lock u1
(
.clock( clock ),
.reset( reset ),
.x( x ),
.ready( ready ),
.unlock( unlock ),
.error( error )
);
endmodule
EDITAR: el segundo bloque siempre cambiado a always@*
ahora desbloqueado y listo parece funcionar, pero el error será igual a uno incluso si la secuencia es correcta. Salida de forma de onda que se muestra a continuación: