How to work with vhdl using free software

The classes of electronic Engineering are usually dictated using popular tools, so I always spend a few hours looking to do my work with FOSS. For this reason, I have decided to share the following guide.

This is a contribution from pandacris, thus becoming one of the winners of our weekly competition: «Share what you know about Linux«. Congratulations!

Installing the necessary

To compile and simulate our programs we will use GHDL, a free compiler based on GCC. To see the simulation results, we will use GTKWAVE. As an editor I recommend Geany as it recognizes almost all programming languages.

sudo apt-get install ghdl gtkwave geany

An example project

Let's use this comparator as an example:

Before creating a project, let's start by creating a folder where all the files will be hosted. In this case, / home / user / vhdl. There we will save the source code of our programs with a .vhd extension.

Then we write our program using Geany, as seen in the screenshot.

We save it as compare.vhd.

Don't forget to save the program with the extension .vhd so that Geany will recognize the format and color the reserved words.

Now we will need to create the signals for the simulation. To do this, we will create a component that uses the previous block and we will specify the signals.

The lines A <= "0011" after 0 ns, "0111" after 5 ns, "0111" after 10 ns; are those that configure the input signals in time

We save the files in / home / user / vhdl. Then, we open a terminal and compile:

ghdl -a compare.vhd

If there are no error messages, the compilation is successful.

Now we compile the "component"

ghdl -a compare_tb.vhd

If there are no errors, we create the executable:

ghdl -e compare_tb

Finally, it remains to perform the simulation and save the results in the one named "compare.vcd"

ghdl -r compare_tb --vcd = compare.vcd

In order to see the results we will use gtkwave:

gtkwave compare.vcd

Once open, use the Ctrl key and the mouse to point to the signals that interest us and press insert. Then double click on the vectors to see the separate signals. Then, right click on the signals to choose the format (binary, hex, octal, decimal, etc.)

If necessary, the magnifying glass button with a square in the center adjusts the graph to the screen.

ALU: arithmetic and logic unit

Okay, now let's do something more interesting: an ALU (aritmethic and logic unit). It will be a logical unit, an arithmetic unit and a multiplexer.

Logical drive (LoU.vhdl)

     LIBRARY ieee; USE IEEE.STD_LOGIC_1164.all; USE IEEE.NUMERIC_STD.all;

ENTITY lou IS
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
END loud;

ARCHITECTURE synth2 OF lou IS
SIGNAL a, b: UNSIGNED (op1'range);
SIGNAL c: UNSIGNED (res'range);
BEGIN
PROCESS (a, b, process)
BEGIN
CASE process IS
WHEN "0000" => c <= RESIZE ((not a), c'length);
WHEN "0001" => c <= RESIZE ((a and b), c'length);
WHEN "0010" => c <= RESIZE ((a or b), c'length);

WHEN "0011" => c <= RESIZE ((a xor b), c'length);
WHEN "0100" => c <= RESIZE ((a nand b), c'length);
WHEN "0101" => c <= RESIZE ((a nor b), c'length);
WHEN OTHERS => null;
ENDCASE;
END PROCESS;

a <= UNSIGNED (op1);
b <= UNSIGNED (op2);
res <= std_logic_vector (c);

END synth2;

Arithmetic unit (ArU.vhd)

     LIBRARY ieee; USE IEEE.STD_LOGIC_1164.all; USE IEEE.NUMERIC_STD.all;

ENTITY aru IS
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
END aru;

ARCHITECTURE synth OF aru IS
SIGNAL a, b: UNSIGNED (op1'range);
SIGNAL c: UNSIGNED (res'range);
BEGIN
PROCESS (a, b, process)
BEGIN
CASE process IS
WHEN "0000" => c <= RESIZE ((a + b), c'length);
WHEN "0001" => c <= RESIZE ((a - b), c'length);
WHEN "0010" => c <= RESIZE ((a * b), c'length);

WHEN "0011" => c <= RESIZE ((a / b), c'length);
WHEN "0100" => c <= RESIZE ((a + "1"), c'length);
WHEN "0101" => c <= RESIZE ((b + "1"), c'length);
WHEN OTHERS => null;
ENDCASE;
END PROCESS;

a <= UNSIGNED (op1);
b <= UNSIGNED (op2);
res <= std_logic_vector (c);

END synth;

Multiplexer (muxVector.vhd)

     LIBRARY ieee; USE IEEE.STD_LOGIC_1164.all; USE IEEE.NUMERIC_STD.all;

ENTITY muxVector IS
PORT (from ARU: IN std_logic_vector (7 DOWNTO 0);
fromLOU: IN std_logic_vector (7 DOWNTO 0);
switch: IN std_logic;
output: out std_logic_vector (7 DOWNTO 0));
END muxVector;

ARCHITECTURE change OF muxVector IS
BEGIN
with switch select
output <= from ARU when '0', from LOU when others;
END change;

ALU Component (aluComponent.vhd)

     LIBRARY ieee; USE IEEE.STD_LOGIC_1164.all; USE IEEE.NUMERIC_STD.all;

ENTITY alu Component IS
END aluComponent;

ARCHITECTURE inputs_aluComponent OF aluComponent IS

COMPONENT aru
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
END COMPONENT;

COMPONENT lou
PORT (op1: IN std_logic_vector (7 DOWNTO 0);
op2: IN std_logic_vector (7 DOWNTO 0);
process: IN std_logic_vector (3 DOWNTO 0);
res: OUT std_logic_vector (7 DOWNTO 0));
END COMPONENT;

COMPONENT muxVector
PORT (from ARU: IN std_logic_vector (7 DOWNTO 0);
fromLOU: IN std_logic_vector (7 DOWNTO 0);
switch: IN std_logic;
output: out std_logic_vector (7 DOWNTO 0));
END COMPONENT;

SIGNAL outputARU: std_logic_vector (7 DOWNTO 0);
SIGNAL outputLOU: std_logic_vector (7 DOWNTO 0);
signal Switch: std_logic;
signal process: std_logic_vector (3 DOWNTO 0);
signal output: std_logic_vector (7 DOWNTO 0);
SIGNAL A: std_logic_vector (7 DOWNTO 0);
SIGNAL B: std_logic_vector (7 DOWNTO 0);

BEGIN
u0: aru PORT MAP (A, B, process, ARU exit);
u1: lou PORT MAP (A, B, process, LOU output);
u2: muxVector PORT MAP (output ARU, output LOU, switch, output);

A <= "00000011" after 0 ns, "00000111" after 5 ns, "00000111" after 10 ns, "00001001" after 15 ns, "00000000" after 20 ns, "00000101" after 25 ns, "00001111" after 30 ns, "00000101" after 35 ns;
B <= "00000010" after 0 ns, "00000100" after 5 ns, "00000010" after 10 ns, "00000011" after 15 ns, "00000100" after 20 ns, "00000110" after 25 ns, "00001111" after 30 ns, "00000011" after 35 ns;
switch <= '1' after 0 ns, '0 ′ after 5 ns,' 1 ′ after 10 ns, '0' after 15 ns, '1 ′ after 20 ns,' 0 ′ after 25 ns, '1 ′ after 30 ns, '0 ′ after 35 ns,' 1 ′ after 40 ns;
process <= "0000" after 0 ns, "0001" after 5 ns, "0010" after 10 ns, "0011" after 15 ns, "0100" after 20 ns, "0101" after 25 ns, "0110" after 30 ns;
END inputs_aluComponent;

To avoid wasting time compiling command by command while working on the program, we save a file called compilar.sh with the following content in the same folder:

ghdl -a lou.vhd && ghdl -a aru.vhd && ghdl -a muxVector.vhd && ghdl -a aluComponente.vhd && ghdl -e aluComponente && ghdl -r aluComponent --vcd = alu&componente.wave

Open a terminal, enter the folder and run the script:

cd / home / user / vhdl sh compile.sh

If there are no errors gtkwave will open and we can see the signals:

These tools have been very useful and easier to use than the proprietary tools we use in class, which suspiciously take too long to compile. With ghdl it takes longer to switch windows than to compile.

More info about VHDL

For those new to vhdl, here they have a basic example of a denier.

An example video:
http://www.youtube.com/watch?v=feVMXsyLSOU

Remember that the latest versions of Ubuntu do not have GHDL in their repositories. This can be downloaded for Linux / Windows from the project page:
http://ghdl.free.fr/site/pmwiki.php?n=Main.Download


Leave a Comment

Your email address will not be published. Required fields are marked with *

*

*

  1. Responsible for the data: Miguel Ángel Gatón
  2. Purpose of the data: Control SPAM, comment management.
  3. Legitimation: Your consent
  4. Communication of the data: The data will not be communicated to third parties except by legal obligation.
  5. Data storage: Database hosted by Occentus Networks (EU)
  6. Rights: At any time you can limit, recover and delete your information.

  1.   Nacho said

    Is there a way that GTKWave will give you the gate circuit it represents?