Disallowed constructs

From FPGA Wiki

Jump to: navigation, search

There are a number of constructs that are commonly used within VHDL that are not able to be synthesized. The more common ones are listed below as well as alternative designs to allow for synthesis.

Shared Variables

For some components such as register-files, it is sometimes convenient to use separate processes to read and write data to the underlying data structure. To do this, the variable containing the data structure must be moved out of a process and into the architecture level so both processes can use it. For example:

architecture behavioral of register_file is

type register_data is array(0 to 7) of STD_LOGIC_VECTOR (31 downto 0);
shared variable regBank: register_data := (
	X"00000000",
	X"00000000",
	X"00000000",
	X"00000000",
	X"00000000",
	X"00000000",
	X"00000000",
	X"00000000"
);
begin
	write_proc: process(clk)
	begin
		-- code
	end process write_proc;

	read_proc: process(read_reg1, read_reg2)
	begin
		read_reg_out1 <= regBank(register1);
		read_reg_out2 <= regBank(register2);
	end process read_proc;
end behavioral;

Unfortunately, the shared keyword is not synthesizeable. An easy fix for this is to change the data structure to a signal rather than a variable, and move the code inside read_proc outside, into the architecture:

architecture behavioral of register_file is

	type register_data is array(0 to 7) of STD_LOGIC_VECTOR (31 downto 0);
	signal regBank: register_data := (
		X"00000000",
		X"00000000",
		X"00000000",
		X"00000000",
		X"00000000",
		X"00000000",
		X"00000000",
		X"00000000"
	);
begin

	write_proc: process(clk)
	begin
		-- code
	end process write_proc;

	read_reg_out1 <= regBank(register1);
	read_reg_out2 <= regBank(register2);
end behavioral;

Because the data is now a signal, it will automatically trigger the bindings to be updated causing read_reg_out1 and read_reg_out2 to update asynchronously.

Storing Data vs. Setting Output to Input

The main difference between placing code on an FPGA and running it in a simulator is latency caused by combinatoric logic from latches. In an effort to remove as many un-needed latches as possible, code that stores data asynchronously and then updates the output to the value of the stored data should be changed. For example:

entity obj is
	port (
		in_data : in std_logic_vector(31 downto 0);
		clk : in std_logic;
		out_data : out std_logic_vector(31 downto 0)
	);
end obj;

architecture behavioral of obj is	  

signal stored_data : std_logic_vector(31 downto 0) := X"00000000";

begin
	proc : process
	begin
		wait until (clk'event and clk='1');
		out_data <= stored_data;
	end process proc;

	stored_data <= in_data;
end behavioral;

Should be changed to:

entity obj is
	port (
		in_data : in std_logic_vector(31 downto 0);
		clk : in std_logic;
		out_data : out std_logic_vector(31 downto 0)
	);
end obj;

architecture behavioral of obj is

begin
	proc : process
	begin
		wait until (clk'event and clk='1');
		out_data <= in_data;
	end process proc;
end behavioral;
Personal tools
extra