Skip navigation
2012
pjclarke

FPGA Design Guide Pt3

Posted by pjclarke Mar 11, 2012

So over the last few months if you have been following my FPGA Design guide you will see that I have first blocked out the chucks of logic I needed, then last time I showed you the code used to get my first part of the temperature display working. However I said last time that having all the code in one block of VHDL makes it hard to read and is not a good idea. So this time lets look at the structure of VHDL and using separate files, ‘components’ and get our heads round the ‘entity’ and ‘architecture’ of VHDL.

So starting with the ‘entity’ statement as this is our top level for any design or sub unit. Its easy to forget when writing VHDL that its hardware, so lets think about this as if we were wiring up real chips on a bread board. The ‘entity’ therefore for the purpose of this example is going to be your chips pin out.

entity counter_30bit is
    Port ( clk_i : in  STD_LOGIC;
           count : out  STD_LOGIC_VECTOR (29 downto 0));
end counter_30bit;

Above is the entity for just our counter.

Counter_30.png

As you can see the entity lists the names of the pins and if its a input or output. All or pins and signals so far have been listed as STD_LOGIC, this is a single wire that can be logic level ‘1’ or ‘0’. When you see a reference to STD_LOGIC_VECTOR then we are talking about a number of wires like a data bus. The statement that follows explains the width and designations of the wires. Here you can see we have 30 wires labeled bit 0 to 29. The reason for the downto keyword explains that its bit 29 that is the MSB.

So next is the architecture and again we look at our counter as a separate unit.

architecture Behavioral of counter_30bit is
signal cnt_r : std_logic_vector(29 downto 0) := (others=>'0');
begin
process(clk_i) is
begin
  if rising_edge(clk_i) then
   cnt_r <= cnt_r + 1;
  end if;
end process;
count <= cnt_r;
end Behavioral;

This section as we have said before is the functanl bit of the VHDL. If this was a chip then its the bit that explains how the device works. Anything in here is completely separate from the outside world and hardware that connects to the block via the port entity can only see the connected signals.

So the next question is how do you connect this counter or ‘chip’ to others to make up your full circuit. Well this we can do via the ‘component’ keyword. From a chip and hardware point of view we would need a Bill of Materials (BOM) and also a Net list so we know what to connect where. In VHDL we will do the same sort of thing.

So if we want to use our counter in our design we first must tell VHDL what it is. This component deceleration is just like our BOM list.

component counter_30bit
port (
   clk_i : in STD_LOGIC;
   count : out STD_LOGIC_VECTOR (29 downto 0)
);
end component;

This looks a lot like the entity and that's because we are just listing the interface. This delectation will appear inside the architecture of the VHDL code before the ‘begin’ statement. After the begin statement in the functionally bit we need to create our Net list connections to other logic.

counter : component counter_30bit
          port map ( clk_i => clk_i,
                          count => cnt_r );

Here we list the component we want to use and then use the ‘port map’ keyword to generate the Net connections. I always think of this as ‘map-ing’ the pins of the chip to the signals. Here we list inside the port map first the pin (clk_i and count are the names used in the component) that then map to the signals in my design ( clk_i and cnt_r are local signals).

Improving on the original design and VHDL below I have attached all the new files. Here I have broken out each sub block and made it into a component. My top level design then only has to connect up the components, bit like wiring up chips on  a bread board.

The advantage of all this is that the blocks are easier to understand and also can be tested alone. Also means that you can use them as many times as you like in a design or in other designs.