Verilog que genera un bit específico del registro a la salida; obteniendo constantes de 1

1

Estoy tratando de crear un programa que toque un valor de un FPGA a un arduino. En el módulo que creé, cada dos ciclos de reloj, la salida de FPGAdata debería establecerse en el siguiente bit de t. El problema es que FPGAdata es igual a 1 todo el tiempo. ¿Qué está causando esto?

module fpgaread(ARDUINOclk, FPGAclk, FPGAdata);
input ARDUINOclk;
output reg FPGAdata;
output reg FPGAclk;


reg [15:0] count=0;
reg [127:0] t =3542638353836;

always @ (posedge ARDUINOclk) begin
        count=count+1;
        if(count%2==0) begin
            FPGAclk = 0;
        end else if (count <= 256) begin
            FPGAdata=t[(count-1)/2];
            FPGAclk = 1;
        end else begin
            count = 0;
        end
end

endmodule

La nota t es solo un número con el que estoy probando. En el futuro, quiero que sea una variable y no solo una constante.

El propósito del < 256 es que quiero enviar 128 bits. En el futuro, agregaría más código en el resto para un restablecimiento, pero esto no afecta la pregunta porque la salida es de 1 antes de que llegue al final.

Estoy utilizando el quartus II v13 con un ciclón II

EDITAR: Aquí hay un esquema de lo que ve el quartus del programa. FPGAdata se acaba de establecer en 1.

    
pregunta Eric Johnson

1 respuesta

2

Creo que lo más probable es que el problema se deba a una combinación de no configurar los anchos de bits correctos para las constantes y usar asignaciones de bloqueo.

En general, es importante establecer el ancho de las constantes que use. Esto no solo elimina las advertencias del sintetizador del truncamiento de las señales, sino que también ayuda a dar al sintetizador una mejor impresión de lo que está intentando inferir. Recuerda, no estás escribiendo código como lo harías para un Arduino, estás describiendo el hardware.

Debido a que está describiendo hardware, no importa la cantidad de líneas de código que tome, ya que reducir la cantidad de líneas no tiene necesariamente ningún impacto en el tamaño del diseño, solo hace que sea más difícil de leer. Tanto para usted como para las herramientas de síntesis. Para ello, divida su diseño en bloques: use múltiples bloques siempre para diferentes grupos de señales. Si tiene un contador, use un bloque separado para que quede claro qué código es para el contador; incluso puede colocarlo en un módulo separado si desea que la salida RTL sea más fácil de leer.

También es una buena práctica atenerse a las tareas de no bloqueo. No voy a entrar en detalles sobre las diferencias, ya que hay preguntas aquí y en StackOverflow que las describen muy bien. Pero basta con decir que hay diferencias sutiles que pueden atraparlo si no tiene cuidado. El uso de todas las funciones de no bloqueo ayuda a mantener a raya estas sutilezas, pero acepto que también requiere un poco de reflexión adicional porque refuerza el hecho de que se trata de un lenguaje HDL y no de procedimientos.

Con lo anterior en mente, he ordenado su código basado en lo anterior. El contador está separado de las otras señales, solo se utilizan instrucciones no bloqueantes, y he corregido los anchos constantes:

module fpgaread(ARDUINOclk, FPGAclk, FPGAdata);

input ARDUINOclk;
output reg FPGAdata;
output reg FPGAclk;


reg [15:0] count= 16'd0;
reg [127:0] t = 128'd3542638353836;

//Counter
always @ (posedge ARDUINOclk) begin
    if (count < 16'd256) begin
        count <= count + 16'd1;
    end else begin
        count <= 16'd0;
    end
end

//External interface
always @ (posedge ARDUINOclk) begin
    if (!count[0]) begin //see if it is even by checking the LSB. You can use %2 if you want, but in complex cases it can infer horrid logic.
        FPGAclk <= 1'b0; //Falling edge
    end else if (count < 16'd256) begin
        FPGAclk <= 1'b1; //Rising edge
        FPGAdata <= t[count[15:1]]; //data goes out on rising edge.
    end
end

endmodule

Como resultado, el RTL inferido es ahora esto:

Mucho mejor.

    
respondido por el Tom Carpenter

Lea otras preguntas en las etiquetas