¿Qué se observa si cambiáis a mitad de recorrido la línea de selección de modo (incremento o decremento), sin limpiar el contador?
Añadid las líneas PRESET y CLEAR activas por bajo y asíncronas a los biestables del contador. Modificad el diseño añadiendo una línea adicional de HOLD, también activa por bajo, de modo que si esa línea está activa, el biestable no responda a la señal T. Auxiliaros de las entradas PRESET y CLEAR para ello, no modifiquéis el interior del biestable T.
Haced una última simulación en la que, cada vez que cambiéis de modo de cuenta, activéis previamente HOLD y la desactivéis después, a fin de que la cuenta cambie de sentido normalmente, sin producirse saltos.
module T(output reg Q, input wire C); always @(negedge C) begin Q=~Q; end initial begin Q=0; end endmodulePonemos nombres a los biestables, las puertas y los cables:
module contador(output wire [3:0] Q, input wire C, input wire DECnINC); wire b1, b2, b3; xor x1(b1, Q[0], DECnINC); xor x2(b2, Q[1], DECnINC); xor x3(b3, Q[2], DECnINC); T T1(Q[0], C); T T2(Q[1], b1); T T3(Q[2], b2); T T4(Q[3], b3); endmoduleConstruimos un módulo de prueba con una señal de reloj de periodo 10. Durante 100 unidades de tiempo ponemos al contador en cuenta descendente y durante las 100 unidades siguientes, en cuenta ascendente:
module prueba; reg rC, rDECnINC; wire [3:0] cQ; contador pedro(cQ, rC, rDECnINC); initial begin $monitor($time," DECnINC=%b, C=%b, Q=%b(%d)", rDECnINC, rC, cQ, cQ); rC=0; rDECnINC=1; #100 rDECnINC=0; #100 $finish; end always begin #5 rC=~rC; end endmoduleLo ejecutamos y nos da el siguiente resultado:
0 DECnINC=1, C=0, Q=1111(15) 5 DECnINC=1, C=1, Q=1111(15) 10 DECnINC=1, C=0, Q=1110(14) 15 DECnINC=1, C=1, Q=1110(14) 20 DECnINC=1, C=0, Q=1101(13) 25 DECnINC=1, C=1, Q=1101(13) 30 DECnINC=1, C=0, Q=1100(12) 35 DECnINC=1, C=1, Q=1100(12) 40 DECnINC=1, C=0, Q=1011(11) 45 DECnINC=1, C=1, Q=1011(11) 50 DECnINC=1, C=0, Q=1010(10) 55 DECnINC=1, C=1, Q=1010(10) 60 DECnINC=1, C=0, Q=1001( 9) 65 DECnINC=1, C=1, Q=1001( 9) 70 DECnINC=1, C=0, Q=1000( 8) 75 DECnINC=1, C=1, Q=1000( 8) 80 DECnINC=1, C=0, Q=0111( 7) 85 DECnINC=1, C=1, Q=0111( 7) 90 DECnINC=1, C=0, Q=0110( 6) 95 DECnINC=1, C=1, Q=0110( 6) 100 DECnINC=0, C=0, Q=1001( 9) 105 DECnINC=0, C=1, Q=1001( 9) 110 DECnINC=0, C=0, Q=1010(10) 115 DECnINC=0, C=1, Q=1010(10) 120 DECnINC=0, C=0, Q=1011(11) 125 DECnINC=0, C=1, Q=1011(11) 130 DECnINC=0, C=0, Q=1100(12) 135 DECnINC=0, C=1, Q=1100(12) 140 DECnINC=0, C=0, Q=1101(13) 145 DECnINC=0, C=1, Q=1101(13) 150 DECnINC=0, C=0, Q=1110(14) 155 DECnINC=0, C=1, Q=1110(14) 160 DECnINC=0, C=0, Q=1111(15) 165 DECnINC=0, C=1, Q=1111(15) 170 DECnINC=0, C=0, Q=0000( 0) 175 DECnINC=0, C=1, Q=0000( 0) 180 DECnINC=0, C=0, Q=0001( 1) 185 DECnINC=0, C=1, Q=0001( 1) 190 DECnINC=0, C=0, Q=0010( 2) 195 DECnINC=0, C=1, Q=0010( 2)El contador funciona del modo esperado. Cada vez que hay una caída de la señal de reloj (pasa de 1 a 0), el contador baja o sube según el modo de cuenta en que lo hayamos colocado. Sin embargo, como dice el enunciado, se produce un pequeño salto en la cuenta cuando se cambia del modo descendente al ascendente (tiempo 100). Este salto tiene sentido pues la salida de las puertas XOR cambia al cambiar la señal
DECnINC
y esto
hace que cambie la entrada T de los biestables.
Lo primero es añadir las líneas PRESET y CLEAR activas por nivel bajo al biestable T. Aprovechamos para construir una salida Q negada para que el biestable quede de lo más completo:
module T(output reg Q, output wire nQ, input wire C, input wire nCLEAR, input wire nPRESET); not N(nQ, Q); always @(negedge C) begin if (nCLEAR==1 && nPRESET==1) Q=~Q; end always @(nCLEAR) begin if (nCLEAR==0) Q=0; end always @(nPRESET) begin if (nPRESET==0) Q=1; end initial begin Q=0; end endmoduleHemos añadido código para que:
nCLEAR
, el
biestable se pone a 0nPRESET
, el
biestable se pone a 1NQ
es un cable conectado con
el registro Q
mediante una puerta NOTnCLEAR
y nPRESET
tengan prioridad sobre la
señal de reloj (instrucción if
del bloque always
de la señal
C
)Seguimos las instrucciones y construimos un módulo
Thold
que tenga un módulo T
interno y una línea adicional, nHOLD
que,
cuando esté activa, haga que el biestable no atienda
a la señal de reloj. Dicho y hecho:
nCLEAR
y
nPRESET
, cuando están activas, se transmiten
prioritariamente al biestable T. Si están inactivas
y nHOLD
también está inactiva, todo
funciona como si el biestable T no estuviera modificado.
Sin embargo, en el caso de que nHOLD
esté
activa (valga 0), Q
se transmite a nCLEAR
y
nQ
se transmite a nPRESET
. El efecto
neto es que, en estas circunstancias, el biestable mantiene
su valor y, como estas líneas son prioritarias,
el biestable no atiende al reloj C
, justo lo que
se pretendía. Pongamos nombres:
Y ahora, el código:
module Thold(output wire Q, output wire nQ, input wire C, input wire nCLEAR, input wire nPRESET, input wire nHOLD); wire cCLEAR, cPRESET, cOC, cOP; T jose(Q, nQ, C, cCLEAR, cPRESET); and aC(cCLEAR, nCLEAR, cOC); or oC(cOC, nHOLD, Q); and aP(cPRESET, nPRESET, cOP); or oP(cOP, nHOLD, nQ); endmoduleEn el módulo
contador
de arriba hay que sustituir
los antiguos T
por los nuevos Thold
. Las
líneas adicionales que tienen se dejan al aire (nQ
)
o inactivas, es decir, igual a 1 (nCLEAR
y
nPRESET
):
module contador(output wire [3:0] Q,input wire C,input wire DECnINC, input wire nHOLD); wire b1,b2,b3; xor x1(b1,Q[0],DECnINC); xor x2(b2,Q[1],DECnINC); xor x3(b3,Q[2],DECnINC); Thold T1(Q[0], , C, 1'b1, 1'b1, nHOLD); Thold T2(Q[1], , b1, 1'b1, 1'b1, nHOLD); Thold T3(Q[2], , b2, 1'b1, 1'b1, nHOLD); Thold T4(Q[3], , b3, 1'b1, 1'b1, nHOLD); endmoduleY, finalmente, en el módulo de prueba. La línea
nHOLD
se activa temporalmente cuando queremos cambiar
el sentido de la cuenta:
module prueba; reg rC; reg rDECnINC; reg rnHOLD; wire [3:0] cQ; contador pedro(cQ,rC,rDECnINC,rnHOLD); initial begin $monitor($time," DECnINC=%b nHOLD=%b C=%b Q=%b(%d)", rDECnINC,rnHOLD,rC,cQ,cQ); rC=0; rDECnINC=1; rnHOLD=1; #99 rnHOLD=0; /* Temporalmente nHOLD a 0 */ #1 rDECnINC=0; #1 rnHOLD=1; /* Restauramos nHOLD a 1 */ #99 $finish; end always begin #5 rC=~rC; end endmoduleLa salida es la esperada:
0 DECnINC=1 nHOLD=1 C=0 Q=1111(15) 5 DECnINC=1 nHOLD=1 C=1 Q=1111(15) 10 DECnINC=1 nHOLD=1 C=0 Q=1110(14) 15 DECnINC=1 nHOLD=1 C=1 Q=1110(14) 20 DECnINC=1 nHOLD=1 C=0 Q=1101(13) 25 DECnINC=1 nHOLD=1 C=1 Q=1101(13) 30 DECnINC=1 nHOLD=1 C=0 Q=1100(12) 35 DECnINC=1 nHOLD=1 C=1 Q=1100(12) 40 DECnINC=1 nHOLD=1 C=0 Q=1011(11) 45 DECnINC=1 nHOLD=1 C=1 Q=1011(11) 50 DECnINC=1 nHOLD=1 C=0 Q=1010(10) 55 DECnINC=1 nHOLD=1 C=1 Q=1010(10) 60 DECnINC=1 nHOLD=1 C=0 Q=1001( 9) 65 DECnINC=1 nHOLD=1 C=1 Q=1001( 9) 70 DECnINC=1 nHOLD=1 C=0 Q=1000( 8) 75 DECnINC=1 nHOLD=1 C=1 Q=1000( 8) 80 DECnINC=1 nHOLD=1 C=0 Q=0111( 7) 85 DECnINC=1 nHOLD=1 C=1 Q=0111( 7) 90 DECnINC=1 nHOLD=1 C=0 Q=0110( 6) 95 DECnINC=1 nHOLD=1 C=1 Q=0110( 6) 99 DECnINC=1 nHOLD=0 C=1 Q=0110( 6) 100 DECnINC=0 nHOLD=0 C=0 Q=0110( 6) 101 DECnINC=0 nHOLD=1 C=0 Q=0110( 6) 105 DECnINC=0 nHOLD=1 C=1 Q=0110( 6) 110 DECnINC=0 nHOLD=1 C=0 Q=0111( 7) 115 DECnINC=0 nHOLD=1 C=1 Q=0111( 7) 120 DECnINC=0 nHOLD=1 C=0 Q=1000( 8) 125 DECnINC=0 nHOLD=1 C=1 Q=1000( 8) 130 DECnINC=0 nHOLD=1 C=0 Q=1001( 9) 135 DECnINC=0 nHOLD=1 C=1 Q=1001( 9) 140 DECnINC=0 nHOLD=1 C=0 Q=1010(10) 145 DECnINC=0 nHOLD=1 C=1 Q=1010(10) 150 DECnINC=0 nHOLD=1 C=0 Q=1011(11) 155 DECnINC=0 nHOLD=1 C=1 Q=1011(11) 160 DECnINC=0 nHOLD=1 C=0 Q=1100(12) 165 DECnINC=0 nHOLD=1 C=1 Q=1100(12) 170 DECnINC=0 nHOLD=1 C=0 Q=1101(13) 175 DECnINC=0 nHOLD=1 C=1 Q=1101(13) 180 DECnINC=0 nHOLD=1 C=0 Q=1110(14) 185 DECnINC=0 nHOLD=1 C=1 Q=1110(14) 190 DECnINC=0 nHOLD=1 C=0 Q=1111(15) 195 DECnINC=0 nHOLD=1 C=1 Q=1111(15)Y el cronograma habla por sí solo: