Wednesday, July 8, 2009

Topic #1 (Part 3): HDL - VHDL

Well, I suppose I should get back to the first topic concerning HDL. We left off discussing the basic syntax of Verilog. Now I would like to create the same dff module in VHDL so that we can compare the two. Below is the module, or as it is called in VHDL, the architecture:



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity dff is
Port (     clk, d: in  std_logic;
            q, qn: out std_logic);
end dff;

architecture Behavioral of dff is
begin
process(clk)
begin
    if clk'EVENT and clk='1' then
       q<=d;         qn<=not d;      end if;     end process; end Behavioral;


The first 4 statements describe typical libraries that Xilinx ISE uses when you create a new VHDL module. Technically in this specific design the first two would only be needed as we are not doing anything with unsigned or arithmetic operations.

VHDL breaks the code into two sections, an "entity" and an "architecture". The job of the entity is to define the I/O ports and the data types that are to be use in the architecture. At the top level of the design (commonly denoted as the TLE), these ports are supposed to be physically accessible on your FPGA and are associated with some form of user constraint file (Xilinx called this the UCF) that defines the pin/pad mappings to these ports and additional timing and signalling characteristics/constraints. In other words, if I were to define a counter that is 8 bits long then each of those bits could be be assigned to some physical location on the FPGA (this could be a package pin or a physical locations that is within the FPGA fabric). If you want to use a signal but don't want to physically represent it on your FPGA, then keep reading as I will be briefly covering where this is done. All statements that are to be defined in the entity should be described between the "entity is" (where is the module name that you are using) and "end " statement. To define the ports we must describe them inside a function called "Port();". Inside Port(), we define the name of the ports, the type of the ports (i.e. "in", "out", "inout"), and the data type of the ports. VHDL has a fairly large number of data types to choose from in comparison to Verilog, but in reality there really are only two data types you need, std_logic and std_logic_vector. As the names suggest, one is a single logic bit and the other is an array of logic bits. Below are some other data types that are built into VHDL
  • Bit
  • Bit_vector
  • Boolean
  • Integer
  • Real
  • Time
  • Character
  • String

After the entity is defined comes the architecture. The architecture defines the underlying function of the VHDL module (in other words, it defines what the module does). The beginning of the architecture is indicated by the keyword "architecture" followed by a name for the architecture this should be unique, by default Xilinx ISE uses "Behavioral" which indicates that the architecture is following a "Behavioral Model". Another common name for an architecture is "Structural" which indicates that a "Structual Model" is being used. This name purely serves to improve readability and understanding of the design as a whole; you could name it whatever you want, but it is recommended that it is an informative name. Note, if you have a design/project with multiple VHDL architectures, you will need to be aware of the name used for each and make sure that each architecture is unique. 


After the architecture name is the keyword "of" which followed by the name of some entity; by having this option is allows you to use a single entity to define multiple architectures. So say you have a D Flip Flip, and a T Flip Flip, they both have the same ports but the inner function differs, this allows you to reuse the entity and keeps the code MUCH MUCH cleaner. This reuse of entities and the fact that all the ports are fully defined in a centralized location is one of the key elements that make VHDL nice, especially when it comes time to debug/troubleshoot.

After declaring what entity the architecture is to use, we use the keyword "is". After the "is" you have an option, you can define additional signals to be used that are internal to the architecture or if you have everything you need you can issue the keyword "begin". In this case we don't need any additional signals so we go right into the architecture description.

In VHDL, you define a "process" that indicates that some sort of process is to be executed on an event general caused by a state change of a signal (such as a clock edge). In this case we use "process(clk)" that says that code will be executed during each clock edge. The contents within the parenthesis is generally refered to as the sensitivity list. Multiple signals/nets can be places in the sensitivity list which basically means if any of the nets within the list change then the process fires off; this allows a designer to describe both synchronous and asynchronous systems/processes. Again each process that is defined should be followed by the "begin" keyword. In this design we want to update the D Flip Flop during each positive edge. In Verilog, this was accomplished by "always @(posedge clk)", in VHDL we use the if statement below:


if clk'EVENT and clk='1' then


This statement says that whenever the clk changes (which is indicated by clk'EVENT ) AND clk is logic high (which is indicated by clk='1') then we update q and qn. Likewise, if we want to update only on negative clk edges we would just change clk='1' to clk='0'. After the q and qn update we just need to end our "if", "process" and "Behavioral" architecture.

Well there you have it, hopefully you got something out of this VERY VERY brief tutorial of Verilog and VHDL. Which one you choose is a matter of preference; sometimes the module is easier to code in Verilog other times it is easier to code in VHDL. VHDL is generally seen to be much more powerful, but it is also very strict in when and where you declare/instantiate signals or other modules.

Coming up next time, I will discuss how to create the bit file to physically program a Xilinx FPGA, how to physical map I/O ports to FPGA pins using a "ucf" file, and how to simulate your design using a testbench.

No comments:

Post a Comment