Para continuar con Verilog Code, primero comprenderemos la estructura del contador Ripple de 4 bits. El bloque de diseño superior consta de cuatro T-Flip Flop. Por el momento, ignore la entrada y salida de T-Flip Flop. Consideremos la estructura exterior general de Ripple Counter. Tenemos dos entradas, es decir, reloj y reinicio y q es la salida. La salida q está en forma de vector de 4 bits.
En Ripple Carry Counter , primero, la señal del reloj pasa a través del primer T Flip Flop. Para el segundo T Flip Flop, la salida del primer T Flip Flop actúa como un reloj y así sucesivamente. El reinicio es el mismo para todas las chanclas T.
Implementemos ahora el bloque contador de ondas.
module ripplecounter(clk,rst,q); input clk,rst; output [3:0]q; // initiate 4 T-FF to update the count tff tf1(q[0],clk,rst); tff tf2(q[1],q[0],rst); tff tf3(q[2],q[1],rst); tff tf4(q[3],q[2],rst); endmodule
Ya que instanciamos tff en ripplecounter, ahora veamos el interior de T Flip Flop. Dentro de T-Flip flop tenemos un D flip flop y un inversor, es decir, no una puerta. Para implementar T-Flip flop necesitamos instanciar d flip y flop, y tenemos clk y reset como entrada y q como salida. Necesitamos un cable adicional d, que además actúa como entrada para el flip-flop D.
module tff(q,clk,rst); // tff takes clk and reset as input // q is output input clk,rst; output q; wire d; // by referring the diagram of tff, // instantiate d flip flop and not gate dff df1(q,d,clk,rst); not n1(d,q); endmodule
D Flip Flop Tabla de verdad para referencia:
clk | primero | d | q |
---|---|---|---|
⇡ | 1 | X | 0 |
⇡ | 0 | 0 | 0 |
⇡ | 0 | 1 | 1 |
Bloque de diseño:
module ripplecounter(clk,rst,q); input clk,rst; output [3:0]q; // initiate 4 T-FF to update the count tff tf1(q[0],clk,rst); tff tf2(q[1],q[0],rst); tff tf3(q[2],q[1],rst); tff tf4(q[3],q[2],rst); endmodule module tff(q,clk,rst); // tff takes clk and reset as input // q is output input clk,rst; output q; wire d; // by referring the diagram of tff, // instantiate d flip flop and not gate dff df1(q,d,clk,rst); not n1(d,q); endmodule module dff(q,d,clk,rst); input d,clk,rst; output q; reg q; // store the output value always @(posedge clk or posedge rst) begin // refer the truth table to provide // values to q based on reset. if(rst) q=1'b0; else q=d; endripplecounter endmodule
Banco de pruebas:
La simulación se utiliza para verificar el bloque de diseño proporcionando los valores de entrada al dut. Necesitamos escribir testbench con referencia al bloque ripplecounter, donde tenemos clk y reset como entrada.
El reloj debe alternar después de una unidad de tiempo específica, por lo que inicialmente proporcionamos clk como 0. Y luego, después de cada 5 unidades de tiempo, alternamos el reloj de 0 a 1 y viceversa en bloque siempre.
initial clk=0; always #5 clk=~clk;
Aquí está la simulación del contador de ondas:
module tb; // input to be stored in reg and output as net(wire) reg clk; reg rst; wire [3:0]q; // instantiate the ripplecounter design block ripplecounter dut(clk,rst,q); // generate clock pulse // initially provide 0 // then inside always block toggle // clock every 5 time units initial clk = 0; always #5 clk = ~clk; // provide reset values as the input initial begin rst = 1; #15 rst = 0; #180 rst = 1; #10 rst = 1; #20 $finish; end initial $monitor("time=%g,rst=%b,clk=%b,q=%d",$time,rst,clk,q); endmodule
Producción:
Como se puede ver cuando el reset es 0, la salida q tiene las actualizaciones de salida del contador, y el conteo.