Thursday, October 7, 2010

Accessing Generic Port on a Xilinx Schematic

 It took me a while to figure out how to access the generic port map of a VHDL entity within the schematic view, so now that Ive managed it, heres a new post about it!

The schematic editor included in Xilinx's ISE isnt very user friendly, though the concept of using a schematic to "program" your FPGA or CPLD is not a bad one... especially using a schematic for the top-level structural design allows you to have a good overview of the overall program structure. But, schematics are yuppy, and yuppies must pay for their fancy user-friendly graphical tools, no? So, lets do what we can with what we've got...

With Xilinx ISE (v12.2), its not possible to include 'variable' quantities in a schematic. That is, the width of a bus or a port (on an instanstiated component) cannot be left variable, where you could modify several bus widths in your schematic by changing a single constant. This is a bit sad. If you want this, you'll have to write VHDL or Verilog. However, if you want to access component internal constants, the generics can be made accessible from the schematic by means of a thing called attributes.

So, suppose weve got the following VHDL entity that we want to include in the schematic:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity usless_block is
  generic (
    WIDTH      : integer := 8;
    MULT       : integer := 20;
    MULT_WIDTH : integer := 5);
  port (
    clk   : in  std_logic;
    reset : in  std_logic;
    data  : in  std_logic_vector (WIDTH-1 downto 0);
    junk  : out std_logic_vector (MULT_WIDTH + WIDTH-1 downto 0));
end usless_block;

architecture Behavioral of usless_block is

  what_process : process (clk, reset)
  begin  -- process what_process
    if reset = '1' then                 -- asynchronous reset (active high)
      junk <= (others => '0');
    elsif clk'event and clk = '1' then  -- rising clock edge
      junk <= data*conv_std_logic_vector(MULT,MULT_WIDTH);
    end if;
  end process what_process;

end Behavioral;

Here, you cant leave the bit widths variable from within your schematic, but you CAN leave the multiplication factor MULT variable. To do that, create the schematic symbol for your entity and instatiate in your schematic:

To specify MULT as a generic in the component, right click on the block and select Symbol >> Edit Symbol
 Now, you are using the symbol editor. Right click on the block, and select Object properties. Add a new attribute by clicking on New on the right side. Type in the name of your generic, its default value for instantiation, and the value type (here, integer):
Now, you need to tell the program that you want the attribute to be associated with the generic map. Click on the new attribute name, MULT, to highlight it, then click the Edit traits button on the right. Select the VHDL category on the left side, then click the following check boxes:

 Save the changes to the schematic symbol, and return to your top-level schematic where you want to instantiate the component. You should get an 'Obsolete Symbol' window popping up now, though sometimes this doesnt happen (bug). If not, close the top level schematic and reopen it. Otherwise, just select the 'obsolete' symbol and click Update.
 Now, the generic is still not visible in the schematic. So, right click the symbol to access the Object properties. Check the box to make this attribute visible, and enter a value for the generic.

Now, the generic will appear in the schematic, where it can be modified, and it will appear like so in the compiled .vhf netlist

library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;
library UNISIM;
use UNISIM.Vcomponents.ALL;

entity top_design is
   port ( );
end top_design;

architecture BEHAVIORAL of top_design is
   signal XLXI_1_clk_openSignal   : std_logic;
   signal XLXI_1_data_openSignal  : std_logic_vector (7 downto 0);
   signal XLXI_1_reset_openSignal : std_logic;
   component usless_block
      generic( MULT : integer :=  0);
      port ( clk   : in    std_logic;
             reset : in    std_logic;
             data  : in    std_logic_vector (7 downto 0);
             junk  : out   std_logic_vector (12 downto 0));
   end component;
   XLXI_1 : usless_block
   generic map( MULT => 15)
      port map (clk=>XLXI_1_clk_openSignal,
                data(7 downto 0)=>XLXI_1_data_openSignal(7 downto 0),

By the way, Xilinx has a tutorial on their documentation site, where one can learn the basics of schematic-based design entry:

1 comment:

  1. this is so usefull for me. I tought the problem was on me, but no I'm still a great engineer :P