Download Synthagate | Automatic Design of External Specification

Automatic Design of External Specification

Synthagate v2.1.0 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:

  1. Clock;

  2. Address;

  3. Input bus of memory;

  4. Control signal;

  5. 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:

Picture1.png

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:

  1. Clock;

  2. First address;

  3. Second address;

  4. First Input bus of memory;

  5. Second Input bus of memory;

  6. Control signal for the first input;

  7. Control signal for the second input;

  8. First output bus of memory;

  9. 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:

Picture2.png

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:

  1. Clock;

  2. First address;

  3. Second address;

  4. First input bus of GPR;

  5. Second input bus of GPR;

  6. First control signal;

  7. Second control signal;

  8. 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.

Picture3.png

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:

  1. Clock;

  2. Input address;

  3. Output address;

  4. The input bus of FIFO;

  5. The control signal to write;

  6. The control signal to read;

  7. 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:

Picture4.png

Read from fifo to br2 via fifo13_addrout and write to fifo from br1 via fifo13_addrin