VHDL con diferentes salidas

0

¿Es un código VHDL válido y sintetizable?

case IR(10 downto 7) is -- RD
    when "0000" => R0 <= RTA;
    when "0001" => R1 <= RTA;
    when "0010" => R2 <= RTA;
    when "0011" => R3 <= RTA;
    when "0100" => R4 <= RTA;
    when "0101" => R5 <= RTA;
    when "0110" => R6 <= RTA;
    when "0111" => R7 <= RTA;
    when "1000" => R8 <= RTA;
    when "1001" => R9 <= RTA;
    when "1010" => R10 <= RTA;
    when "1011" => R11 <= RTA;
    when "1100" => R12 <= RTA;
    when "1101" => R13 <= RTA;
    when "1110" => R14 <= RTA;
    when "1111" => R15 <= RTA;
    when others => null ;
end case;

Como se ve en cada caso, la señal de salida es diferente: R0, R1, R2, etc. Pensé que tal vez tendría que poner todas las salidas en cada caso; Algo como esto:

case IR(10 downto 7) is -- RD
    when "0000" => 
       R0 <= RTA;
       R1 <= 0;  -- The problem here is that I don't want R1 to be 0
                 --   but to retain its previous value
       R2 <= 0;
       R3 <= 0;
       R4 <= 0;
       R5 <= 0;
       R6 <= 0;
       R7 <= 0;
       R8 <= 0;
       R9 <= 0;
       R10 <= 0;
       R11 <= 0;
       R12 <= 0;
       R13 <= 0;
       R14 <= 0;
       R15 <= 0;
    when "0001" => 
       R0 <= 0;
       R1 <= RTA;
       R2 <= 0;
       R3 <= 0;
       R4 <= 0;
       R5 <= 0;
       R6 <= 0;
       R7 <= 0;
       R8 <= 0;
       R9 <= 0;
       R10 <= 0;
       R11 <= 0;
       R12 <= 0;
       R13 <= 0;
       R14 <= 0;
       R15 <= 0;
    .
    .
    .
    when others => null ;
end case;

Si no tengo todas las salidas (R0 a R15) en cada caso, el compilador VHDL me da una advertencia: "Se encontró un enclavamiento de 1 bit para la señal. Se pueden generar pestillos a partir de un caso incompleto o declaraciones if. no se recomienda el uso de cierres en los diseños FPGA / CPLD, ya que pueden dar lugar a problemas de tiempo ".

Necesito deshacerme de esta advertencia.

    
pregunta Ehsan

3 respuestas

1

Verilog y VHDL son lenguajes de descripción de hardware, pero se parecen a los lenguajes de programación de procedimientos. En ocasiones, esto puede llevar a un código que sea técnicamente válido pero no sintetizable.

En su primer código de ejemplo, cada salida no especificada explícitamente con un nuevo valor, retiene implícitamente su valor anterior (porque eso es lo que sucedería en un lenguaje de programación de procedimientos). Ese es el "cierre implícito" sobre el que están advirtiendo las herramientas de síntesis. Este código HDL puede ser técnicamente válido, pero puede no ser capaz de sintetizarse (o quizás no de la forma prevista). El problema es que la herramienta de síntesis no puede hacer lo que quiere sin sintetizar también la memoria real para almacenar los valores, y no está claro que es lo que quiere. Aparentemente no le dijiste que creara ninguna memoria para almacenar esos valores.

Su segundo código de ejemplo determina explícitamente el valor de cada salida en cada caso, por lo que la herramienta de síntesis entiende exactamente lo que desea. En su segundo ejemplo, solo una salida obtiene el valor RTA, y el resto de las salidas son 0. Esto es válido y se puede sintetizar, sin embargo usted menciona en los comentarios que esto no es realmente lo que quiere, realmente desea para actualizar un registro manteniendo los valores de los otros registros.

Para escribir el código HDL que actualiza el valor de un registro seleccionado, debe declarar los elementos de memoria reales. No soy un tipo de VHDL, pero en Verilog tal vez escriba algo como esto:

// declare R0..R15 as register storage (memory), not just signal wires
reg[7:10] R0;
reg[7:10] R1;
// etc...
reg[7:10] R15;
// could be written more efficiently as a register file instead of individual registers

// update a register selected by IR[10:7] with data RTA
always @(posedge clock)
begin
    case(IR[10:7])
    4'b0000: 
        R0 <= RTA;
        break;
    4'b0001: 
        R1 <= RTA;
        break;
    // etc.
    4'b1111: 
        R15 <= RTA;
        break;
    endcase
    // 
end
    
respondido por el MarkU
1

El propio case se adhiere a la sintaxis VHDL, y en general las herramientas de síntesis manejan el case .

La advertencia está relacionada con el estilo de codificación general. Si se usa process para crear una lógica combinatoria, entonces todas las señales derivadas de un proceso siempre deben asignarse para evitar bloqueos, pero mi suposición sin ver el resto de su código es que no es así. Un buen estilo de codificación (cuando sea posible) es asignar todas las señales al comienzo del proceso, como:

process (IR, RTA, ...) is
begin
    R0 <= ...;
    R1 <= ...;
    ...
    case ...
end;

Para evitar la advertencia y los pestillos, asegúrese de que todas las señales dirigidas desde un proceso combinatorio estén asignadas.

Por ejemplo, este código creará un bloqueo intencionalmente, ya que q se retiene si en = '0' , y solo se actualiza si en = '1' :

process (en, d) is
begin
    if en = '1' then
        q <= d;
    end if;
end process;

Para la lógica secuencial no hay el mismo problema, ya que los flip-flops solo pueden contener el estado si no se actualizan.

    
respondido por el Morten Zilmer
1

Esta sentencia CASE es válida VHDL. Un uso normal del mismo sería incrustado en una declaración if rising_edge(clk) then , en cuyo caso no generará un pestillo sino un registro cronometrado.

Luego, el primer formulario actualiza un registro en el borde de un reloj, preservando el valor de todos los demás.

El segundo formulario actualiza un registro, borrando todos los demás (lo que rara vez es lo que quieres hacer). Se puede simplificar enormemente moviendo una asignación predeterminada antes de la sentencia CASE ...

if rising_edge(clk) then
   R0 <= 0;
   R1 <= 0;
   -- etc
   case () is
   when 0 => R0 <= RTA;
   -- etc
   end case;
end if;

Aquí, la regla de "la última asignación gana" en procesos síncronos se encarga de las acciones predeterminadas, anulando solo la que usted desea.

Aparte de eso: cada vez que vea grandes declaraciones de CASE regulares como esta, es probable que estén listas para una gran simplificación: considere lo siguiente, lo que elimina el CASE por completo.

type Register is natural range 0 to 255;
type Register_File is array (0 to 15) of Register;
signal R : Register_File;
-- optional if you need teh original register names somewhere...
alias R0 : Register is R(0); -- etc for each register

...

    if rising_edge(clk) then
       -- optional second case
       -- R <= (others => 0);  
       R(to_integer(unsigned(IR(10 downto 7)))) <= RTA;
    end if;

Si las declaraciones CASE son irregulares, la simplificación no es tan fácil.

    
respondido por el Brian Drummond

Lea otras preguntas en las etiquetas