Verilog lecturas asincrónicas de registros y pregunta de diseño

Estoy tratando de entender cuál es el siguiente código de comportamiento, en qué tipo de hardware se convierte:

reg [7:0] k0, k1, k2, k3;
reg [7:0] data1_tmp, data2_tmp;

// Asynchronously read data from two registers
always @(*)
begin
    case (reg1)
        0: data1_tmp = k0;
        1: data1_tmp = k1;
        2: data1_tmp = k2;
        3: data1_tmp = k3;
    endcase
    case (reg2)
        0: data2_tmp = k0;
        1: data2_tmp = k1;
        2: data2_tmp = k2;
        3: data2_tmp = k3;
    endcase
end

Lógicamente entiendo lo que está haciendo. Pero me gustaría saber de qué estaría hecho este mini archivo de registro en hardware. En particular, la matriz de 4x8 bits que consta de k0,k1,k2,k3. Pensé que cuando se trataba de registros y matrices como esta, ¿necesita un reloj para leer datos, como RAM?

Mire, tengo un problema conceptual al diseñar un módulo de caché verilog simple. Tengo una matriz de datos que contiene todas mis etiquetas así:

reg [NUM_TAG_BITS-1:0] tag_array[NUM_BLOCKS-1:0] 

Y tengo un cable "line_select" (desde mi PC de entrada). Lo que quiero hacer es recuperar tag_array[line_select] y luego ponerlo en un comparador con la etiqueta de mi PC para ver si tengo un acierto.

Pero pensé que cada vez que accedo a tag_array, necesito estar dentro del código "always @ (posedge clk)". Luego me quedé atascado: ¿cómo leo de este tag_array y hago la comparación dentro del mismo ciclo de reloj? Así que encontré el código anterior en línea que dice que puede leer los registros de forma asincrónica, luego me confundí porque, francamente, no sé lo suficiente sobre el hardware de memoria y cómo es posible.

¡Muchas gracias por cualquier ayuda!

Respuestas (2)

Su código simula dos multiplexores. Estos son en realidad componentes asincrónicos. El hecho de que Verilog requiera data1_tempy data2_tempse declare como reg's es una peculiaridad de la sintaxis de Verilog y su elección de estilo de codificación, y no significa que estas señales sean las salidas de los elementos de almacenamiento en una implementación física.

Si desea capturar estos valores en registros reales, debe agregarlos explícitamente:

reg [7:0] data1, data2;
always @(posedge someclock) begin
    data1 <= data1_tmp;
    data2 <= data2_tmp;
end

Pero me gustaría saber de qué estaría hecho este mini archivo de registro en hardware. En particular, la matriz de 4x8 bits que consta de k0,k1,k2,k3.

No ha mostrado cómo se asignan estas variables, por lo que no es posible decir cómo se implementan. Como mostró su código, simplemente declararlos como regno garantiza que se implementen con elementos de almacenamiento reales. Si los asigna dentro de un bloque que comienza always @(posedge clk), es muy probable que sean flip-flops, pero hay formas de codificarlos que los sintetizarían de manera diferente.

Pensé que cuando se trataba de registros y matrices como esta, ¿necesita un reloj para leer datos, como RAM?

Necesita un reloj para actualizar un registro (físico). Puedes leerlo en cualquier momento. Por ejemplo:

wire [8:0] sum;
assign sum = k0 + k1; 

es un código perfectamente válido. sumcambiará cada vez que cambie alguna de sus entradas. Si k0y k1son las salidas de los flip-flops, sus valores solo cambiarán cuando haya un borde de reloj.

Para otro ejemplo, igualmente podría describir sus multiplexores con un código como este:

reg [7:0] k0, k1, k2, k3;
wire [7:0] data1_tmp;
reg [1:0] reg1;
// k<n> and reg1 are assigned elsewhere.
assign data1_tmp = (reg1 == 0) ? k0 :
                   (reg1 == 1) ? k1 :
                   (reg1 == 2) ? k2 : k3;

¿Cómo leo de este tag_array y hago la comparación dentro del mismo ciclo de reloj?

Permítanme repetir un punto clave para enfatizar: necesita usar un reloj para asignar un nuevo valor a un registro (un registro de hardware real o un grupo de flip-flops). Su salida está disponible en cualquier momento.

Las RAM son diferentes y la forma de acceder al contenido de una RAM dependerá de los detalles del tipo de RAM que utilice.

Me confundí porque, francamente, no sé lo suficiente sobre hardware de memoria y cómo es posible.

Otra estrategia clave: cuando esté aprendiendo lógica digital, le recomiendo que primero aprenda sobre el hardware físico y luego trabaje o estudie cómo simularlo en HDL en segundo lugar. Entonces, primero, aprenda qué es un flip-flop físico, luego aprenda los métodos estándar de Verilog para describir un flip-flop. Especialmente si está tratando de escribir HDL para síntesis, tratar de escribir un buen código antes de aprender las capacidades del hardware subyacente lo llevará por muchos caminos sin salida.

¡Muchas gracias! Esta parte realmente me llegó a casa: Let me repeat a key point for emphasis: You need to use a clock to assign a new value to a register (an actual hardware register or group of flip-flops). It's output is available at any time.dibujé en papel un montón de DFF y me di cuenta de esto... Por supuesto, las salidas están disponibles en cualquier momento y las escrituras deben estar sincronizadas con un reloj. Como usted sugiere, estoy tratando de aprender los conceptos de hardware más que la codificación. Gracias de nuevo.
@YoungMoney, me alegro de haber podido ayudar. Normalmente le sugiero que espere 24 horas para aceptar una respuesta para alentar más respuestas. Pero 1) Dave Tweed es la persona aquí con más probabilidades de dar una buena respuesta a una pregunta de Verilog, y ya ha respondido. 2) Creo que mi respuesta es bastante buena. No obstante, si aparece otra respuesta que te ayude más, siéntete libre de rechazar la mía. Y hay un par de otros usuarios aquí que podrían dar buenas respuestas si se sienten tan conmovidos.
@Photon: ¡Agradezco el cumplido! He estado diseñando con FPGA durante mucho tiempo, pero recientemente comencé a ponerme al día específicamente con Verilog. La mayor parte de mi trabajo anterior fue en VHDL, y antes de eso, captura esquemática. Estoy muy interesado en el proyecto de YoungMoney, porque una parte importante de mi carrera estuvo relacionada con el diseño de CPU de alto rendimiento, incluidas MMU y cachés.
@DaveTweed, sé que hay otros aquí que pueden responder a una pregunta como esta --- pero ciertamente estás en una lágrima cuando se trata de aparecer para responder. Simplemente no te quemes como StevenVH --- acumuló 40k repeticiones en un año y luego básicamente desapareció.

Si un Verilog se convierte o no regen un flip-flop de hardware depende de cómo se actualice. En general, si se actualiza dentro de un always @(posedge <signal>)bloque, se convertirá en un DFF.

Su código de muestra no muestra cómo se actualizan k0, k1, k2 y k3, por lo que en lo que respecta a este bloque, son solo 32 cables que provienen de otro lugar. Cada casedeclaración es un multiplexor asíncrono simple que selecciona 8 bits a la vez de entre esos 32 cables.

k<n>Si sus variables se pueden mapear colectivamente o no en una estructura de RAM de hardware (suponiendo que tal cosa esté disponible en su tecnología de destino) depende de cómo se actualizan y cómo se leen ... y qué tan buenas son las herramientas de síntesis para inferir RAM del código de comportamiento.