===== 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: -- 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. -------------------------------------------------------------------------------- -- 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. 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:ghdl_sim_results.png?direct&800 }}