pub:dglab_ghdl

GHDL es una utilidad de la terminal de software libre para simular ficheros cuya descripción hardware se encuentra escrita en el lenguaje VHDL. Se ha incluido en dglab para dar soporte a VHDL, aunque en menor medida que a Verilog.

Como ejemplo de su utilización, vamos a usar Icarus Verilog para convertir el anterior diseño de la ALU a VHDL. Como comentamos anteriormente, esto es posible definiendo vhdl como target de la simulación.

iverilog -t vhdl -o alu.vhd alu.v

Este comando genera un archivo alu.vhd que contiene una traducción de la ALU a vhdl, obtenida a través del fichero alu.v. El código VHDL del fichero generado se muestra a continuación:

alu.vhd
-- This VHDL was converted from Verilog using the
-- Icarus Verilog VHDL Code Generator 0.9.7  (v0_9_7)
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
 
-- Generated from Verilog module alu (alu.v:8)
entity alu is
  port (
    A : in unsigned(7 downto 0);
    B : in unsigned(7 downto 0);
    C : out std_logic;
    Z : out std_logic;
    op : in unsigned(1 downto 0);
    result : out unsigned(7 downto 0)
  );
end entity;
 
-- Generated from Verilog module alu (alu.v:8)
architecture FromVerilog of alu is
  signal C_Reg : std_logic := '0';
  signal Z_Reg : std_logic := '0';
  signal result_Reg : unsigned(7 downto 0) := "00000000";
begin
  C <= C_Reg;
  Z <= Z_Reg;
  result <= result_Reg;
 
  -- Generated from always process in alu (alu.v:28)
  process (op, B, A) is
    variable Verilog_Assign_Tmp_0 : unsigned(8 downto 0);
    variable Verilog_Assign_Tmp_1 : unsigned(8 downto 0);
    variable Verilog_Assign_Tmp_2 : unsigned(8 downto 0);
    variable Verilog_Assign_Tmp_3 : unsigned(8 downto 0);
    variable Verilog_Assign_Tmp_4 : unsigned(8 downto 0);
  begin
    case op is
      when "00" =>
        Verilog_Assign_Tmp_0 := (Resize(A, 9) + Resize(B, 9));
        result_Reg <= Verilog_Assign_Tmp_0(7 downto 0);
        C_Reg <= Verilog_Assign_Tmp_0(8);
      when "01" =>
        Verilog_Assign_Tmp_1 := ('0' & (A and B));
        result_Reg <= Verilog_Assign_Tmp_1(7 downto 0);
        C_Reg <= Verilog_Assign_Tmp_1(8);
      when "10" =>
        Verilog_Assign_Tmp_2 := ('0' & (A or B));
        result_Reg <= Verilog_Assign_Tmp_2(7 downto 0);
        C_Reg <= Verilog_Assign_Tmp_2(8);
      when "11" =>
        Verilog_Assign_Tmp_3 := ('0' & (not A));
        result_Reg <= Verilog_Assign_Tmp_3(7 downto 0);
        C_Reg <= Verilog_Assign_Tmp_3(8);
      when others =>
        Verilog_Assign_Tmp_4 := "000000000";
        result_Reg <= Verilog_Assign_Tmp_4(7 downto 0);
        C_Reg <= Verilog_Assign_Tmp_4(8);
    end case;
  end process;
 
  -- Generated from always process in alu (alu.v:38)
  process (result_Reg) is
  begin
    if (Resize(result_Reg, 9) = "000000000") then
      Z_Reg <= '1';
    else
      Z_Reg <= '0';
    end if;
  end process;
end architecture;

Se puede observar que se mantiene la misma descripción, y se genera una arquitectura traducida “desde verilog”, que podrá ser suplementada con diferentes descripciones hardware más adaptadas al lenguaje.

Para simular el archivo resultante, necesitaremos un testbench. Un ejemplo de un posible testbench escrito en vhdl se muestra a continuación.

alu_tb.vhd
--------------------------------------------------------------------------------
-- Entity: alu_tb
-- Date:2015-11-24
-- Author: usuario
--
-- Description: Testbench para la ALU
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
 
entity alu_tb is
end alu_tb;
 
architecture test of alu_tb is
    signal A: unsigned (7 downto 0) := "00000000";
    signal B: unsigned (7 downto 0) := "00000000";
    signal C: std_logic;
    signal Z: std_logic;
    signal op: unsigned (1 downto 0) := "00";
    signal result: unsigned (7 downto 0);
begin
 
    uut: entity work.alu(FromVerilog)
        port map(A, B, C, Z, op, result);
 
    stimulus: process is
    begin
    -- Valores iniciales
    A <= "00001000";
    B <= "00001101";
    -- Recorremos las operaciones
    for I in 0 to 3 loop
        wait for 10 ns;
        op <= op + 1;
    end loop;
    -- Cambio de valores
    A <= "00101000";
    B <= "11011000";
    -- Recorremos las operaciones
    for I in 0 to 3 loop
        wait for 10 ns;
        op <= op + 1;
    end loop;
 
    wait;
 
    end process stimulus;
end test;

Llamaremos a este fichero alu_tb.vhd. Si se prefiere, para comprobar errores de sintaxis, puede ser editado con Eclipse. Como se puede observar, el objetivo de este testbench consiste en dar dos argumentos, A y B e ir a través de todas las operaciones comprobando el correcto funcionamiento.

Una vez tenemos ambos archivos disponibles para el diseño, lo más sencillo para simularlo es utilizar un Makefile muy simple.

Los Makefiles son ficheros que utiliza la utilidad de terminal make, que se encarga, entre otras cosas de ayudar a ejecutar una serie de comandos de forma rápida, típicamente para la compilación de una aplicación o ejecutable. La siguiente trama de código muestra el Makefile que utilizaremos.

Makefile
all:
    ghdl -a alu.vhd # Análisis de alu.vhd
    ghdl -e alu # Elaboración de la alu
    ghdl -a alu_tb.vhd # Análisis de alu_tb.vhd
    ghdl -e alu_tb # Elaboración de la alu_tb
    ghdl -r alu_tb --stop-time=100ns --vcd=alu_tb_vhdl.vcd # Simulación del testbench
    rm alu alu.o alu_tb alu_tb.o e~alu.o e~alu_tb.o work-obj93.cf # Borrado de archivos temporales
 
clear:
    rm alu alu.o alu_tb alu_tb.o alu_tb_vhdl.vcd e~alu.o e~alu_tb.o work-obj93.cf

Como se puede observar, se encargará de generar primero el análisis del fichero alu.vhd. Posteriormente, se elabora la unidad alu, que se reconoce gracias al comando anterior. Se debe realizar lo mismo para el testbench, y por último, se simula y se vuelcan las entradas y salidas al fichero alu_tb_vhdl.vcd. Finalmente, se eliminan los archivos temporales creados.

Para ejecutar el Makefile basta con encontrarse en el mismo directorio que los ficheros de simulación y ejecutar el comando:

make

Tras ejecutar el comando, aparecerá el fichero alu_tb_vhdl.vcd en el directorio de trabajo. Basta con hacer doble click sobre el para abrir GTKWave y examinar el resultado de la simulación, que se muestra a continuación:

  • pub/dglab_ghdl.txt
  • Última modificación: 2020/09/28 11:44
  • (editor externo)