Contador de anillos en verilog

1

Tengo la tarea de diseñar un contador de anillo en verilog usando el operador de cambio. Aquí está el código hasta ahora junto con el banco de pruebas:

module ring (

input wire [3:0] data,
input wire clk,
input wire rst,
input wire load,
output reg [3:0] q 
) ;

/*When the load pin is High, the data is loaded in the counter on clock transition.
* Otherwise the data is shifted  upon each clock. 
* Last output is fed back to the first input.
*/

initial     q = 4'b1010 ;

reg tmp = 1'b0 ;

always @ (posedge clk, posedge rst)
begin
if(rst)
    begin
    q <= 4'b0000 ;
    end
else if(load)
    begin
    q[3] <= data[3] ;
    q[2] <= data[2] ;
    q[1] <= data[1] ;
    q[0] <= data[0] ;
    end

else
    begin
    tmp = q[0] ;
    q = q >> 1 ;
    q[3] = tmp ;
    end
end
endmodule 

Banco de pruebas

'timescale 1 ns / 1 ns

module ringTest ;

//Signals
reg [3:0] data = 4'b1010 ;
wire [3:0] q = 4'b0000 ;
reg clk = 1'b0 ;
reg rst = 1'b0 ;
reg load = 1'b0 ;

//Instantiate uut
ring uut (  .data(data),
    .q(q),
    .clk(clk),
    .rst(rst),
    .load(load)
);

always  #10 clk = ~clk ;

/*Load data every 100 s
always  
begin
#95 load = 1'b1 ;
#5 load = 1'b0 ;
end
*/
//Data to be loaded
always 
begin
if ( data == 4'b1111) data <= 4'b0000 ;
else    begin
    # 50 data <= data + 4'b0001 ;
    end
end
endmodule

Nota: He deshabilitado temporalmente la funcionalidad de carga porque el contador no estaba funcionando. Así que en lugar de eso, opté por cambiar los datos con un valor inicial, que tampoco funcionó. La salida es siempre X.

¿A dónde me voy mal?

Gracias.

    

1 respuesta

1

En primer lugar, los comandos iniciales no se utilizan en el código de Verilog sintetizable. Y no estoy seguro de si sigo por qué lo está utilizando, dado que ya tiene un estado de restablecimiento.

En segundo lugar, en su otra declaración, está usando una asignación de bloqueo en "tmp = q [0]" que está bien, porque almacena el valor q [0] en una variable interna del proceso.

Lo que no está bien, continúa utilizando las asignaciones de bloqueo en "q = q < < 1" y en "q [3] = tmp". No tiene ningún sentido, está modelando una salida secuencial, debe modelarla utilizando una asignación no bloqueante como: "q < = q < < 1" y "q [3] < = temp". No sé lo que hará el simulador, pero probablemente cambiará la señal q tan pronto como ejecute esta línea, y no en el próximo reloj de borde ascendente como debería esperar. Como el sintetizador no será capaz de hacer eso, tendrá un comportamiento de hardware que no será modelado por su simulación. (muy serio)

También he notado que no realiza un reinicio en su módulo. Esto es seguramente una mala práctica, lo primero que debe hacer, antes de inyectar cualquier información en su módulo es restablecerlo.

Por último, ¿ha verificado en su forma de onda que tiene un flanco ascendente al mismo tiempo que envía un nivel de señal de carga alto? Por lo que he leído en su banco de pruebas, no creo que esto ocurra.

¿Entonces no reinicia su módulo, no envía una carga en un flanco ascendente y se queja de que su salida está en X? Bueno, deberías volver a leer todos los conceptos básicos de Verilog y aprender a usar correctamente un simulador.

    
respondido por el gstorto

Lea otras preguntas en las etiquetas