Download Synthagate | Automatic Design of External Specification
Automatic Design of External Specification
Synthagate v2.1.1 automatically builds external specifications for most external components. External specifications do not need to be constructed by hand. For successful implementation, we recommend naming external components with a specific prefix and ordering signals in the component entities as indicated below. This will not affect the quality of your design, which is independent of the order of the signals in the entity. Nevertheless, there are no restrictions on the architecture of your VHDL code.
The following is for external components such as memory, dual memory, GPR (general purpose register), FIFO, and ALU.
External Memory. To describe the external memory in the folder Components, the file name must begin with mem. For example, memAlt65536x16.vhd, MemXilM1, MemLatM0, mem1, mem2, memMyGirlfriend, etc.
​
The order of ports in the entities of the external components should be as follows:
-
Clock;
-
Address;
-
Input bus of memory;
-
Control signal;
-
Output bus of memory.
Example of VHDL code for memory:
​
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity memAlt65536x8 is
generic
(
address_width : integer := 16;
data_width : integer := 8
);
port
(
clock : in std_logic;
address : in std_logic_vector(address_width - 1 downto 0);
data : in std_logic_vector(data_width - 1 downto 0);
wren : in std_logic;
q : out std_logic_vector(data_width - 1 downto 0)
);
end memAlt65536x8;
architecture rtl of memAlt65536x8 is
type memAlt65536x8 is array(0 to 2**address_width-1) of
std_logic_vector(data_width - 1 downto 0);
signal memAlt65536x8_block : memAlt65536x8;
begin
process (clk)
begin
if (clk'event and clk = '1') then
if (ctr = '1') then
mem65536x8_block(to_integer(unsigned(adr))) <= din;
end if;
dout <= mem65536x8_block(to_integer(unsigned(adr)));
end if;
end process;
Note: Any architecture and any names in the entity can be used in the above order of signals.
Use the exact same names of ports in ASMs:
Read m2tobr and Write br2m2
External Dual Memory. To describe the external dual memory in the folder Components, the file name must begin from dmem. For example, dmemAlt65536x16.vhd, dMemXilM1, dMemLatM0, dmem1, dmem2, dmemMyBoyfriend, etc.
​
The order of ports in the entities of the external components should be as follows:
-
Clock;
-
First address;
-
Second address;
-
First Input bus of memory;
-
Second Input bus of memory;
-
Control signal for the first input;
-
Control signal for the second input;
-
First output bus of memory;
-
Second output bus of memory.
Example of VHDL code for dual memory:
​
library ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
entity dmem65536x8 is
GENERIC
(
address_width : integer := 16;
data_width : integer := 8
);
port
(
clock : in std_logic;
address_a : in std_logic_vector(address_width - 1 downto 0);
address_b : in std_logic_vector(address_width - 1 downto 0);
data_a : in std_logic_vector(data_width - 1 downto 0);
data_b : in std_logic_vector(data_width - 1 downto 0);
wren_a : in std_logic;
wren_b : in std_logic;
q_a : out std_logic_vector(data_width - 1 downto 0);
q_b : out std_logic_vector(data_width - 1 downto 0)
);
end dmem65536x8;
architecture rtl of dmem65536x8 is
-- Build a 2-D array type for the RAM
subtype word_t is std_logic_vector(data_width - 1 downto 0);
type memory_t is array(0 to 2 ** address_width - 1) of word_t;
-- Declare the ram
shared variable ram : memory_t;
begin
-- Port A
process(clock)
begin
if(rising_edge(clock)) then
if(wren_a = '1') then
ram(to_integer(unsigned(address_a))) := data_a;
end if;
q_a <= ram(to_integer(unsigned(address_a)));
end if;
end process;
-- Port B
process(clock)
begin
if(rising_edge(clock)) then
if(wren_b = '1') then
ram(to_integer(unsigned(address_b))) := data_b;
end if;
q_b <= ram(to_integer(unsigned(address_b)));
end if;
end process;
end rtl;
Note: Any architecture and any names in the entity can be used in the above order of signals.
Use the exact same names of ports in ASMs:
Read from m0 to ext_in via address_b and write to m1 from ext_out via address_a
General purpose register (GPR). To describe the external GPR in the folder Components, the file name must begin from gpr. For example, gprRISCV.vhd, gpr16x4, gpr1, gprXil32x32, gprMommy, gprDaddy, etc
​
The order of ports in the entities of the external components should be as follows:
-
Clock;
-
First address;
-
Second address;
-
First input bus of GPR;
-
Second input bus of GPR;
-
First control signal;
-
Second control signal;
-
First output bus of GPR;
Example of VHDL code for GPR:
​
This GPR is constructed from registers. Thus, it isn’t possible to write simultaneously into two registers – for that, we use the first address or second address. However, the reading is possible via two addresses at once.
-----------------------------------------------
library IEEE;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-----------------------------------------------
entity gpr is
generic
(
address_width : integer := 4;
data_width : integer := 16
);
port
(
clock : in std_logic;
rst : in std_logic;
address1 : in std_logic_vector (address_width-1 downto 0);
address2 : in std_logic_vector (address_width-1 downto 0);
data1 : in std_logic_vector (data_width-1 downto 0);
data2 : in std_logic_vector (data_width-1 downto 0);
wren1 : in std_logic;
wren2 : in std_logic;
q1 : out std_logic_vector (data_width-1 downto 0);
q2 : out std_logic_vector (data_width-1 downto 0)
);
end gpr;
-----------------------------------------------
architecture arch_gpr of gpr is
type gpr_type is array (0 to 2 ** address_width-1) of std_logic_vector (data_width - 1 downto 0);
signal gpr : gpr_type;
begin
-- port 1
process(clock, rst)
begin
if (rising_edge(clock) and rst = '1') then
for i in 0 to 2 ** address_width-1 loop
gpr (i) <= (others => '0');
end loop;
elsif (clock'event and clock = '1') then
if (wren1 = '1') then
gpr(to_integer(unsigned(address1))) <= data1;
end if;
if (wren2 = '1') then
gpr(to_integer(unsigned(address2))) <= data2;
end if;
end if;
end process;
q1 <= gpr (to_integer(unsigned(address1))); -- Read from address1
q2 <= gpr (to_integer(unsigned(address2))); -- Read from address2
end arch_gpr;
Note: Any architecture and any names in the entity can be used in the above order of signals.
Reading from GPR with two addresses in br1 and br2 and writing to GPR via address_a and address_b
FIFO. To describe the external FIFO in the folder Components, the file name must begin from fifo. For example, fifoRISCV.vhd, fifo16x4-1, fifoXil32x32, fifoMommy, fifoDaddy, etc.
​
The order of ports in the entities of the external components should be as follows:
-
Clock;
-
Input address;
-
Output address;
-
The input bus of FIFO;
-
The control signal to write;
-
The control signal to read;
-
The output bus of FIFO.
Example of VHDL code for FIFO:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
entity fifo13 is
generic (
depth : integer := 4;
data_width : integer := 4
);
port (
clk : in std_logic;
addrin : in std_logic_vector(depth-1 downto 0);
addrout : in std_logic_vector(depth-1 downto 0);
din : in std_logic_vector(data_width-1 downto 0);
wren : in std_logic;
rden : in std_logic;
dout : out std_logic_vector(data_width-1 downto 0)
);
end fifo13;
architecture rtl of fifo13 is
type ram_t is array(0 to 2**depth-1) of std_logic_vector(depth-1 downto 0);
signal ram : ram_t;
signal data : std_logic_vector(depth-1 downto 0):=(others =>'0');
begin
process (clk)
begin
if (clk'event and clk = '1') then
if (wren = '1') then
ram(conv_integer(addrin)) <= din;
end if;
end if;
end process;
process (clk)
begin
if (clk'event and clk = '1') then
if (rden = '1') then
dout<=data;
data <= ram(conv_integer(addrout));
end if;
end if;
end process;
end rtl;
​
Note: Any architecture and any names in the entity can be used in the above order of signals.
​
Use the exact same names of ports in ASMs:
Read from fifo to br2 via fifo13_addrout and write to fifo from br1 via fifo13_addrin