--
-- Hail Simulation Components
--
--
-- Link Connect module
--
-- Behavioral model of a single link connection
-- DST_RDY always '1'
-- Routes TX signals to RX
library ieee;
use ieee.std_logic_1164.all;
library work;
use work.common_interface.all;
use work.hail_simulation.all;
entity link_connect is
port (
linkA_out : in link_out_type;
linkA_in : out link_in_type;
linkB_out : in link_out_type;
linkB_in : out link_in_type);
end link_connect;
architecture behave of link_connect is
begin
linkA_in.tx_dst_rdy <= '1';
linkB_in.tx_dst_rdy <= '1';
linkA_in.rx_data <= linkB_out.tx_data;
linkA_in.rx_src_rdy <= linkB_out.tx_src_rdy;
linkA_in.rx_sof <= linkB_out.tx_sof;
linkA_in.rx_eof <= linkB_out.tx_eof;
linkB_in.rx_data <= linkA_out.tx_data;
linkB_in.rx_src_rdy <= linkA_out.tx_src_rdy;
linkB_in.rx_sof <= linkA_out.tx_sof;
linkB_in.rx_eof <= linkA_out.tx_eof;
end behave;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;
library work;
use work.common_interface.all;
use work.hail_simulation.all;
entity hail_simulator is
generic (
board : board_type := adm_xp;
number_of_memories : integer := 6);
port (
clk : in std_logic;
rst : in std_logic;
system_out : in std_logic_vector(system_width-1 downto 0);
system_in : out std_logic_vector(system_width-1 downto 0);
links_in : in links_in_type;
links_out : out links_out_type;
host_in : in host_in_type;
host_out : out host_out_type);
end hail_simulator;
architecture behave of hail_simulator is
signal ctrl_bus_ivec : std_logic_vector(ctrl_bus_width-1 downto 0) := (others => '0');
signal status_bus_ivec : std_logic_vector(status_bus_width-1 downto 0) := (others => '0');
signal irq_bus_ivec : std_logic_vector(interrupt_bus_width-1 downto 0) := (others => '0');
signal bram_bus_ivec : std_logic_vector(bram_bus_width-1 downto 0) := (others => '0');
signal locallinks_ivec : std_logic_vector(4*locallink_type_width-1 downto 0) := (others => '0');
signal extrams_ivec : std_logic_vector(6*extmem_type_width-1 downto 0) := (others => '0');
signal ctrl_bus_ovec : std_logic_vector(ctrl_bus_width-1 downto 0) := (others => '0');
signal status_bus_ovec : std_logic_vector(status_bus_width-1 downto 0) := (others => '0');
signal irq_bus_ovec : std_logic_vector(interrupt_bus_width-1 downto 0) := (others => '0');
signal bram_bus_ovec : std_logic_vector(bram_bus_width-1 downto 0) := (others => '0');
signal locallinks_ovec : std_logic_vector(4*locallink_type_width-1 downto 0) := (others => '0');
signal extrams_ovec : std_logic_vector(6*extmem_type_width-1 downto 0) := (others => '0');
signal lclk_dummy : std_logic := '0';
signal irq_bus : interrupt_bus_type := (ier => (others => '0'),
isr => (others => '0'));
type extmem_array_type is array (0 to 5) of extmem_type;
signal eram_in,eram_out : extmem_array_type;
type locallink_array is array (0 to 3) of locallink_type;
signal locallinks_o,locallinks_i : locallink_array;
constant bank_size : integer := 2**16;
type memory_bank_type is array (0 to bank_size-1) of integer;
type memory_bank_array is array (0 to number_of_memories-1) of memory_bank_type;
type q_type is array (0 to 5) of std_logic_vector(63 downto 0);
signal q : q_type;
signal ram_gnt : std_logic_vector(5 downto 0) := "000000";
signal ram_busy : std_logic_vector(5 downto 0) := "000000";
type qpipe_type is array (0 to 15) of std_logic_vector(63 downto 0);
begin
-- Split output system signals and convert data types
split0 : split_system_signal(
system => system_out,
lclk => lclk_dummy,
ctrl_bus => ctrl_bus_ovec,
status_bus => status_bus_ovec,
irq_bus => irq_bus_ovec,
bram_bus => bram_bus_ovec,
locallinks => locallinks_ovec,
extrams => extrams_ovec);
-- Merge signals into system inputs
merge0 : build_system_signal (
system => system_in,
lclk => host_in.clk,
ctrl_bus => ctrl_bus_ivec,
status_bus => status_bus_ivec,
irq_bus => irq_bus_ivec,
bram_bus => bram_bus_ivec,
locallinks => locallinks_ivec,
extrams => extrams_ivec);
-- Connect Local Bus signals directly to host procedures
host_out.status_bus <= slv_to_status_bus(status_bus_ovec);
host_out.interrupt_bus <= slv_to_irq_bus(irq_bus_ovec);
host_out.bram_bus <= slv_to_bram_bus(bram_bus_ovec);
ctrl_bus_ivec <= ctrl_bus_to_slv(host_in.ctrl_bus);
status_bus_ivec <= status_bus_to_slv(host_in.status_bus);
irq_bus_ivec <= irq_bus_to_slv(irq_bus);
bram_bus_ivec <= bram_bus_to_slv(host_in.bram_bus);
-- Update IER only on IER write strobe
process (host_in.interrupt_bus.ier_wstb)
begin -- process
if host_in.interrupt_bus.ier_wstb'event and host_in.interrupt_bus.ier_wstb = '1' then
irq_bus.ier <= host_in.interrupt_bus.ier;
end if;
end process;
irq_bus.isr <= host_in.interrupt_bus.isr;
-- Connect Local Links to local link ports
split_ll_out: for i in 0 to 3 generate
locallinks_o(i) <= slv_to_locallink_type(locallinks_ovec((i+1)*locallink_type_width-1 downto i*locallink_type_width));
links_out(i).tx_data <= locallinks_o(i).tx_data;
links_out(i).tx_src_rdy <= locallinks_o(i).tx_src_rdy;
links_out(i).tx_sof <= locallinks_o(i).tx_sof;
links_out(i).tx_eof <= locallinks_o(i).tx_eof;
locallinks_i(i).tx_dst_rdy <= links_in(i).tx_dst_rdy;
locallinks_i(i).rx_data <= links_in(i).rx_data;
locallinks_i(i).rx_src_rdy <= links_in(i).rx_src_rdy;
locallinks_i(i).rx_sof <= links_in(i).rx_sof;
locallinks_i(i).rx_eof <= links_in(i).rx_eof;
end generate split_ll_out;
locallinks_ivec <= locallink_type_to_slv(locallinks_i(3)) & locallink_type_to_slv(locallinks_i(2))& locallink_type_to_slv(locallinks_i(1)) & locallink_type_to_slv(locallinks_i(0));
-- Model External RAM banks internally
connect_ram: for i in 0 to number_of_memories-1 generate
eram_out(i) <= slv_to_extmem_type(extrams_ovec((i+1)*extmem_type_width-1 downto i*extmem_type_width));
extrams_ivec((i+1)*extmem_type_width-1 downto i*extmem_type_width) <= extmem_type_to_slv(eram_in(i));
-- Behavioural module of multi-clock access to RAM
model_ram: process (host_in.clk,clk,rst)
variable mem_msw,mem_lsw : memory_bank_type;
variable qpipe : qpipe_type;
variable qvpipe : std_logic_vector(15 downto 0);
begin -- process model_ram
if rst = '1' then
for j in 0 to bank_size-1 loop
mem_msw(j) := 0;
mem_lsw(j) := 0;
end loop; -- i
ram_gnt(i) <= '0';
ram_busy(i) <= '0';
for j in 0 to 15 loop
qpipe(j) := (others => '0');
qvpipe(j) := '0';
end loop; -- j
eram_in(i).gnt <= '0';
eram_in(i).q <= (others => '0');
eram_in(i).qv <= '0';
eram_in(i).full <= '0';
elsif rising_edge(clk) then
if ram_gnt(i) = '1' and ram_busy(i) = '0' then
if eram_out(i).w = '1' then
mem_msw(CONV_INTEGER(eram_out(i).a)) := CONV_INTEGER(eram_out(i).d(63 downto 32));
mem_lsw(CONV_INTEGER(eram_out(i).a)) := CONV_INTEGER(eram_out(i).d(31 downto 0));
elsif eram_out(i).r = '1' then
qpipe(0) := CONV_STD_LOGIC_VECTOR(mem_msw(CONV_INTEGER(eram_out(i).a)),32) & CONV_STD_LOGIC_VECTOR(mem_lsw(CONV_INTEGER(eram_out(i).a)),32);
end if;
qvpipe(0) := eram_out(i).r;
else
qvpipe(0) := '0';
end if;
eram_in(i).gnt <= ram_gnt(i);
eram_in(i).full <= ram_busy(i);
for j in 15 downto 1 loop
qpipe(j) := qpipe(j-1);
qvpipe(j) := qvpipe(j-1);
end loop; -- j
eram_in(i).q <= qpipe(15);
eram_in(i).qv <= qvpipe(15);
elsif rising_edge(host_in.clk) then
if host_in.extmem_bus.bank = i then
if host_in.extmem_bus.gnt = '1' then
ram_gnt(i) <= '1';
elsif host_in.extmem_bus.clrgnt = '1' then
ram_gnt(i) <= '0';
elsif host_in.extmem_bus.wstb = '1' then
mem_msw(host_in.extmem_bus.addr) := CONV_INTEGER(host_in.extmem_bus.data(63 downto 32));
mem_lsw(host_in.extmem_bus.addr) := CONV_INTEGER(host_in.extmem_bus.data(31 downto 0));
elsif host_in.extmem_bus.rstb = '1' then
q(i) <= CONV_STD_LOGIC_VECTOR(mem_msw(host_in.extmem_bus.addr),32) & CONV_STD_LOGIC_VECTOR(mem_lsw(host_in.extmem_bus.addr),32);
end if;
end if;
end if;
end process model_ram;
end generate connect_ram;
process (host_in.extmem_bus.addr,q,host_in.clk)
begin -- process
host_out.extmem_bus.data <= q(host_in.extmem_bus.bank);
if rising_edge(host_in.clk) then
host_out.extmem_bus.req <= eram_out(host_in.extmem_bus.bank).req;
end if;
end process;
end behave;