Cómo insertar valores en una matriz 2d en verilog

0

Escribí un código verilog para el registro de Cambio Circular utilizando una matriz 2-d, pero parece que no puedo insertar valores en la matriz. Aquí está mi código

    module cir_shift_reg_v(
        input CLK,
        output reg [16:0] BYTE_OUT
    );

    reg [16:0] byteShiftReg[9:0] = {16'h0,16'h1,16'h2,16'h3,16'h4,16'h5,16'h6,16'h7,16'h8,16'h9};
    integer i,j;

    always @(posedge CLK)
    begin
        BYTE_OUT <= byteShiftReg[0]; 
        for (i=0;i<9;i=i+1)
            byteShiftReg[i] <= byteShiftReg[i+1];

        byteShiftReg[9] <= BYTE_OUT;    
    end
    endmodule

Recibo un error durante la simulación que dice

    Constant value or constant expression must be used for initialization
    
pregunta Ashutosh Jain

1 respuesta

1

Esto es algo importante para entender. Verilog es un lenguaje de descripción de hardware, lo que significa que lo que está haciendo no es escribir código en los arreglos 2D de acceso y, por lo tanto, está escribiendo código que describe qué hardware se requiere. En algo como C (un lenguaje de procedimiento), la inicialización de una matriz es algo que se realiza en tiempo de ejecución: la CPU copia el contenido de la matriz de la memoria del programa a la RAM y luego puede usarla. Sin embargo aquí no tienes ese paso.

Además, la sintaxis que está intentando usar es algo de C, no de Verilog. De hecho, en Verilog, {} significa concatenación. Entonces, en esencia, lo que está haciendo es concatenar diez valores de 16 bits en un único vector de 160 bits. Entonces intenta asignarlo como el valor de inicialización a una RAM que no es del mismo tamaño. ¿Cómo encaja un vector 1x160 en una memoria de 10x16bit?

También tenga en cuenta que su registro se declara de tamaño incorrecto; usted dice que lo desea con 16 bits, pero que ha hecho de cada uno 17 bits ([16: 0] = 17b).

Tienes dos opciones a considerar.

Opción 1

La primera opción es dividir las cosas un poco. En lugar de intentar hacer todo de una vez, considere lo que hace su hardware. En esencia, lo que tiene no es una RAM, sino dieciséis registros de desplazamiento circular de 10 bits. Todos trabajan sincronizados entre sí, sí, pero en realidad son dieciséis copias del mismo hardware, así que trabajemos con eso. ¿Cómo hacemos dieciséis copias idénticas de algo? Dos opciones, crear un módulo e instanciarlo dieciséis veces, o más simplemente usar algo llamado generate loop: es básicamente un bucle for que instancia múltiples copias de hardware. Vamos a usar la segunda opción.

parameter INITIAL_VALUE = {16'h0,16'h1,16'h2,16'h3,16'h4,16'h5,16'h6,16'h7,16'h8,16'h9}; //Concatenate our initial values into a single parameter.

genvar j; //This is our generate loop variable.
generate for (j = 0; j < 16; j=j+1) begin : shift_reg_loop //shift_reg_loop is just a name for the loop. It can be any valid HDL name.

    //Now we instantiate one 10bit circular shift register
    reg [9:0] byteShiftReg; //Just 1 bit of the 16.
    integer i;
    initial begin
        for (i=0;i<9;i=i+1) begin
            byteShiftReg[i] = INITIAL_VALUE[i*16+j]; //Initialise each bit with the correct value extracted from our initial value.
        end
    end

    always @ (posedge CLK) begin
        BYTE_OUT[j] <= byteShiftReg[0]; 
        for (i=0;i<9;i=i+1) begin
            byteShiftReg[i] <= byteShiftReg[i+1];
        end
        byteShiftReg[9] <= BYTE_OUT[j];    
    end

end endgenerate //end of for loop and generate statement.

Opción 2

Habiendo dicho todo lo anterior, en realidad, en su caso, realmente no necesita dividir las cosas, pero primero quería presentarles la opción de darle una idea de lo que está pasando debajo del capó, por así decirlo. y le dará información útil para futuros trabajos.

Podemos usar una de las cosas que introduje en el otro ejemplo para inicializar la memoria directamente, el llamado bloque initial . Esto te permite hacer varias cosas "al principio". Recuerda cómo dije que para un programa de C, la inicialización de la matriz se realiza en tiempo de ejecución. Bueno, en Verilog es posible hacer algo similar pero en síntesis . En otras palabras, podemos inicializar la matriz indicando al sintetizador cuál será el valor predeterminado para cada registro (valor de encendido).

Para grupos multidimensionales de registros, como memorias, podemos definir un bloque inicial que puede hacer cosas muy similares a su bloque siempre. En este caso para bucles.

parameter initialValue = {16'h0,16'h1,16'h2,16'h3,16'h4,16'h5,16'h6,16'h7,16'h8,16'h9}; //This works because concatenation makes it a 160bit wide value.

reg [15:0] byteShiftReg[9:0];

initial begin
    for (i=0;i<9;i=i+1) begin
        //Extract each 16bit chunk in turn from the initial value parameter
        //and use that as the initial value for this part of the shift register.
        // Note the (9-i) bit is used because concatenation of the initial value places the first value in the most significant bits, and last value in the least significant bits.
        byteShiftReg = initialValue[((9-i)*16)+:16];
    end
end

integer i;

always @(posedge CLK)
begin
    BYTE_OUT <= byteShiftReg[0]; 
    for (i=0;i<9;i=i+1) begin
        byteShiftReg[i] <= byteShiftReg[i+1];
    end
    byteShiftReg[9] <= BYTE_OUT;    
end
endmodule
    
respondido por el Tom Carpenter

Lea otras preguntas en las etiquetas