From fb8606313f1b6a930668e40e9634a1aa9b74daa0 Mon Sep 17 00:00:00 2001 From: hadeshyp Date: Thu, 24 May 2007 11:12:20 +0000 Subject: [PATCH] added trb_net_med_8bit_fast.vhd and necessary data converters and fifos, Jan --- trb_net_18_to_16_converter.vhd | 307 +++++++++++ trb_net_55_to_18_converter.vhd | 252 +++++++++ trb_net_fifo_16bit_bram_dualport.vhd | 20 + trb_net_med_8bit_fast.vhd | 503 +++++++++++++++++ .../trb_net_fifo_16bit_bram_dualport_arch.vhd | 513 ++++++++++++++++++ 5 files changed, 1595 insertions(+) create mode 100644 trb_net_18_to_16_converter.vhd create mode 100644 trb_net_55_to_18_converter.vhd create mode 100644 trb_net_fifo_16bit_bram_dualport.vhd create mode 100644 trb_net_med_8bit_fast.vhd create mode 100644 xilinx/trb_net_fifo_16bit_bram_dualport_arch.vhd diff --git a/trb_net_18_to_16_converter.vhd b/trb_net_18_to_16_converter.vhd new file mode 100644 index 0000000..070ffdf --- /dev/null +++ b/trb_net_18_to_16_converter.vhd @@ -0,0 +1,307 @@ + +----------------------------------- +--D18 data structure +-- XXXXXXXX0+++++++ 00 +-- 1+++++++2+++++++ 01 +-- 3+++++++4+++++++ 10 +-- 5+++++++6+++++++ 11 +------------------------------------ +--X unused, / error+parity, + data +------------------------------------ +--D16 data structure +-- 0+++++++1+++++++ 00 +-- 2+++++++3+++++++ 01 +-- 4+++++++5+++++++ 10 +-- 6+++++++//////// 11 +----------------------------------- + + + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.STD_LOGIC_ARITH.ALL; +USE IEEE.STD_LOGIC_UNSIGNED.ALL; +use work.trb_net_std.all; + +--Entity decalaration for clock generator +entity trb_net_18_to_16_converter is + generic ( VERSION : integer := 0); --Version of included sbufs + port( + -- Misc + CLK : in std_logic; + RESET : in std_logic; + CLK_EN : in std_logic; + + D18_DATAREADY_IN: in STD_LOGIC; + D18_PACKET_NUM_IN: in STD_LOGIC_VECTOR(1 downto 0); + D18_DATA_IN: in STD_LOGIC_VECTOR (15 downto 0); -- Data word + D18_READ_OUT: out STD_LOGIC; + + D16_DATAREADY_OUT: out STD_LOGIC; + D16_DATA_OUT: out STD_LOGIC_VECTOR (15 downto 0); -- Data word + D16_READ_IN: in STD_LOGIC; + D16_PACKET_NUM_OUT: out STD_LOGIC_VECTOR(1 downto 0); + + D18_DATAREADY_OUT: out STD_LOGIC; + D18_PACKET_NUM_OUT: out STD_LOGIC_VECTOR(1 downto 0); + D18_DATA_OUT: out STD_LOGIC_VECTOR (15 downto 0); -- Data word + D18_READ_IN: in STD_LOGIC; + + D16_DATAREADY_IN: in STD_LOGIC; + D16_DATA_IN: in STD_LOGIC_VECTOR (15 downto 0); -- Data word + D16_READ_OUT: out STD_LOGIC; + D16_PACKET_NUM_IN: in STD_LOGIC_VECTOR(1 downto 0) + ); +end entity; + +architecture trb_net_18_to_16_converter_arch of trb_net_18_to_16_converter is + component trb_net_sbuf + generic (DATA_WIDTH : integer := 16; + VERSION: integer := 0); + port( + -- Misc + CLK : in std_logic; + RESET : in std_logic; + CLK_EN : in std_logic; + -- port to combinatorial logic + COMB_DATAREADY_IN: in STD_LOGIC; --comb logic provides data word + COMB_next_READ_OUT: out STD_LOGIC; --sbuf can read in NEXT cycle + COMB_READ_IN: in STD_LOGIC; --comb logic IS reading + -- the COMB_next_READ_OUT should be connected via comb. logic to a register + -- to provide COMB_READ_IN (feedback path with 1 cycle delay) + -- The "REAL" READ_OUT can be constructed in the comb via COMB_next_READ_ + -- OUT and the READ_IN: If one of these is ='1', no problem to read in next + -- step. + COMB_DATA_IN: in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); -- Data word + -- Port to synchronous output. + SYN_DATAREADY_OUT: out STD_LOGIC; + SYN_DATA_OUT: out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); -- Data word + SYN_READ_IN: in STD_LOGIC; + -- Status and control port + STAT_BUFFER: out STD_LOGIC + ); + END component; + +signal dbuf18_comb_dataready_in : std_logic; +signal dbuf18_next_read_out : std_logic; +signal dbuf18_comb_read_in : std_logic; +signal dbuf18_comb_data_in, buf_D16_DATA_OUT : std_logic_vector(17 downto 0); +signal dbuf18_status : std_logic_vector(31 downto 0); +signal buffer_dbuf18_comb_data_in : std_logic_vector(7 downto 0); +signal next_buffer_dbuf18_comb_data_in : std_logic_vector(7 downto 0); +signal next_buf_D18_READ_OUT, buf_D18_READ_OUT : std_logic; +signal D18_PACKET4, last_D18_PACKET4 : std_logic; + + +signal dbuf16_comb_dataready_in : std_logic; +signal dbuf16_next_read_out : std_logic; +signal dbuf16_comb_read_in : std_logic; +signal dbuf16_comb_data_in, buf_D18_data_out : std_logic_vector(17 downto 0); +signal dbuf16_status : std_logic_vector(31 downto 0); +signal buffer_dbuf16_comb_data_in : std_logic_vector(7 downto 0); +signal next_buffer_dbuf16_comb_data_in : std_logic_vector(7 downto 0); +signal next_buf_D16_READ_OUT, buf_D16_READ_OUT : std_logic; +signal D16_packet, next_D16_packet : std_logic_vector(1 downto 0); + + + +begin + +----------------------------------------------------------- +--Direction 18 to 16 +----------------------------------------------------------- + + +next_buf_D18_READ_OUT <= dbuf18_next_read_out or dbuf18_comb_read_in; +D18_READ_OUT <= buf_D18_READ_OUT; + + D18to16 : process(buffer_dbuf18_comb_data_in, dbuf18_comb_data_in, last_D18_PACKET4, + buf_D18_READ_OUT, D18_DATAREADY_IN, D18_PACKET_NUM_IN, D18_DATA_IN) + variable newdata : std_logic; + begin + if buf_D18_READ_OUT = '1' and D18_DATAREADY_IN = '1' then + newdata := '1'; + else + newdata := '0'; + end if; + + dbuf18_comb_dataready_in <= '0'; + next_buffer_dbuf18_comb_data_in <= buffer_dbuf18_comb_data_in; + dbuf18_comb_data_in <= dbuf18_comb_data_in; + D18_PACKET4 <= '0'; + + if newdata = '1' and D18_PACKET_NUM_IN /= "00" then + dbuf18_comb_data_in(7 downto 0) <= D18_DATA_IN(15 downto 8); + else + dbuf18_comb_data_in(7 downto 0) <= (others => '0'); + end if; + + if newdata = '1' or last_D18_PACKET4 = '1' then + dbuf18_comb_data_in(15 downto 8) <= buffer_dbuf18_comb_data_in; + if last_D18_PACKET4 = '0' then + dbuf18_comb_data_in(17 downto 16) <= D18_PACKET_NUM_IN - 1; + else + dbuf18_comb_data_in(17 downto 16) <= "11"; + end if; + else + dbuf18_comb_data_in(15 downto 8) <= (others => '0'); + dbuf18_comb_data_in(17 downto 16) <= "00"; + end if; + + if (D18_PACKET_NUM_IN /= "00" and newdata = '1') or last_D18_PACKET4 = '1' then + dbuf18_comb_dataready_in <= '1'; + end if; + + if D18_PACKET_NUM_IN = "11" and newdata = '1' then + D18_PACKET4 <= '1'; + end if; + + if newdata = '1' then + next_buffer_dbuf18_comb_data_in <= D18_DATA_IN(7 downto 0); + end if; + + end process; + + process(CLK, RESET) + begin + if RESET = '1' then + buffer_dbuf18_comb_data_in <= (others => '0'); + last_D18_PACKET4 <= '0'; + buf_D18_READ_OUT <= '0'; + elsif rising_edge(CLK) then + buffer_dbuf18_comb_data_in <= next_buffer_dbuf18_comb_data_in; + last_D18_PACKET4 <= D18_PACKET4; + buf_D18_READ_OUT <= next_buf_D18_READ_OUT; + else + buffer_dbuf18_comb_data_in <= buffer_dbuf18_comb_data_in; + last_D18_PACKET4 <= last_D18_PACKET4; + buf_D18_READ_OUT <= buf_D18_READ_OUT; + end if; + end process; + + + DBUF18 : trb_net_sbuf --dbuf from 18Bit to 16Bit + generic map(DATA_WIDTH => 18, VERSION => VERSION) + port map ( + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + COMB_DATAREADY_IN => dbuf18_comb_dataready_in, + COMB_next_READ_OUT => dbuf18_next_read_out, + COMB_READ_IN => dbuf18_comb_read_in, + COMB_DATA_IN => dbuf18_comb_data_in, + -- Port to synchronous output. + SYN_DATAREADY_OUT => D16_DATAREADY_OUT, + SYN_DATA_OUT => buf_D16_DATA_OUT, + SYN_READ_IN => D16_READ_IN, + -- Status and control port + STAT_BUFFER => dbuf18_status(0) + ); + +D16_DATA_OUT <= buf_D16_DATA_OUT(15 downto 0); +D16_PACKET_NUM_OUT <= buf_D16_DATA_OUT(17 downto 16); + + dbuf18_read_in_gen : process(CLK, RESET) + begin + if RESET = '1' then + dbuf18_comb_read_in <= '0'; + elsif rising_edge(CLK) then + dbuf18_comb_read_in <= dbuf18_next_read_out; + else + dbuf18_comb_read_in <= dbuf18_comb_read_in; + end if; + end process; + + +----------------------------------------------------------- +--Direction 16 to 18 +----------------------------------------------------------- + +next_buf_D16_READ_OUT <= dbuf16_next_read_out; +D16_READ_OUT <= buf_D16_READ_OUT; + + D16to18 : process(buffer_dbuf16_comb_data_in, dbuf16_comb_data_in, + buf_D16_READ_OUT, D16_DATAREADY_IN, D16_DATA_IN, D16_PACKET_NUM_IN) + variable newdata : std_logic; + begin + + if buf_D16_READ_OUT = '1' and D16_DATAREADY_IN = '1' then + newdata := '1'; + else + newdata := '0'; + end if; + + dbuf16_comb_dataready_in <= newdata; + --next_buffer_dbuf16_comb_data_in <= buffer_dbuf16_comb_data_in; + --dbuf16_comb_data_in <= dbuf16_comb_data_in; + + dbuf16_comb_data_in(17 downto 16) <= D16_PACKET_NUM_IN; + + if newdata = '1' then + dbuf16_comb_data_in(7 downto 0) <= D16_DATA_IN(15 downto 8); + else + dbuf16_comb_data_in(7 downto 0) <= (others => '0'); + end if; + + if newdata = '1' then + if D16_PACKET_NUM_IN = "11" then + next_buffer_dbuf16_comb_data_in <= (others => '0'); + else + next_buffer_dbuf16_comb_data_in <= D16_DATA_IN(7 downto 0); + end if; + else + next_buffer_dbuf16_comb_data_in <= buffer_dbuf16_comb_data_in; + end if; + end process; + + process(CLK, RESET) + begin + if RESET = '1' then + buffer_dbuf16_comb_data_in <= (others => '0'); + --D16_packet <= "00"; + buf_D16_READ_OUT <= '0'; + elsif rising_edge(CLK) then + buffer_dbuf16_comb_data_in <= next_buffer_dbuf16_comb_data_in; + --D16_packet <= next_D16_packet; + buf_D16_READ_OUT <= next_buf_D16_READ_OUT; + else + buffer_dbuf16_comb_data_in <= buffer_dbuf16_comb_data_in; + --D16_packet <= D16_packet; + buf_D16_READ_OUT <= buf_D16_READ_OUT; + end if; + end process; + + + DBUF16 : trb_net_sbuf --dbuf from 16Bit to 18Bit + generic map(DATA_WIDTH => 18, VERSION => VERSION) + port map ( + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + COMB_DATAREADY_IN => dbuf16_comb_dataready_in, + COMB_next_READ_OUT => dbuf16_next_read_out, + COMB_READ_IN => dbuf16_comb_read_in, + COMB_DATA_IN => dbuf16_comb_data_in, + -- Port to synchronous output. + SYN_DATAREADY_OUT => D18_DATAREADY_OUT, + SYN_DATA_OUT => buf_D18_data_out, + SYN_READ_IN => D18_READ_IN, + -- Status and control port + STAT_BUFFER => dbuf16_status(0) + ); + +D18_DATA_OUT <= buf_D18_data_out(15 downto 0); +D18_PACKET_NUM_OUT <= buf_D18_data_out(17 downto 16); + + dbuf16_read_in_gen : process(CLK, RESET) + begin + if RESET = '1' then + dbuf16_comb_read_in <= '0'; + elsif rising_edge(CLK) then + dbuf16_comb_read_in <= dbuf16_next_read_out; + else + dbuf16_comb_read_in <= dbuf16_comb_read_in; + end if; + end process; + +end architecture; \ No newline at end of file diff --git a/trb_net_55_to_18_converter.vhd b/trb_net_55_to_18_converter.vhd new file mode 100644 index 0000000..ed1b11f --- /dev/null +++ b/trb_net_55_to_18_converter.vhd @@ -0,0 +1,252 @@ +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.STD_LOGIC_ARITH.ALL; +USE IEEE.STD_LOGIC_UNSIGNED.ALL; +use work.trb_net_std.all; + +--Entity decalaration for clock generator +entity trb_net_55_to_18_converter is + port( + -- Misc + CLK : in std_logic; + RESET : in std_logic; + CLK_EN : in std_logic; + + D55_DATA_IN : in std_logic_vector(55 downto 0); + D55_DATAREADY_IN : in std_logic; + D55_READ_OUT : out std_logic; + + D18_DATA_OUT : out std_logic_vector(15 downto 0); + D18_PACKET_NUM_OUT : out std_logic_vector(1 downto 0); + D18_DATAREADY_OUT : out std_logic; + D18_READ_IN : in std_logic; + + D55_DATA_OUT : out std_logic_vector(55 downto 0); + D55_DATAREADY_OUT : out std_logic; + D55_READ_IN : in std_logic; + + D18_DATA_IN : in std_logic_vector(15 downto 0); + D18_PACKET_NUM_IN : in std_logic_vector(1 downto 0); + D18_DATAREADY_IN : in std_logic; + D18_READ_OUT : out std_logic + ); +end entity; + + +architecture trb_net_55_to_18_converter_arch of trb_net_55_to_18_converter is + + + +type CONV_STATE is (IDLE, FIRST, SECOND, THIRD, LAST); +signal D55to18_state, next_D55to18_state : CONV_STATE; +signal D18to55_state, next_D18to55_state : CONV_STATE; + +signal next_D55_READ_OUT, buf_D55_READ_OUT : std_logic; +signal next_D18_DATAREADY_OUT, buf_D18_DATAREADY_OUT : std_logic; +signal next_D18_PACKET_NUM_OUT, buf_D18_PACKET_NUM_OUT : std_logic_vector(1 downto 0); +signal next_D18_DATA_OUT, buf_D18_DATA_OUT : std_logic_vector(15 downto 0); + + +signal next_D18_READ_OUT, buf_D18_READ_OUT : std_logic; +signal next_D55_DATAREADY_OUT, buf_D55_DATAREADY_OUT : std_logic; + + +signal next_buf_D55_DATA_IN, buf_D55_DATA_IN : std_logic_vector(47 downto 0); +signal next_D55_DATA_OUT, buf_D55_DATA_OUT : std_logic_vector(55 downto 0); + +begin +----------------------------------------------------------- +--Direction 18 to 55 +----------------------------------------------------------- + + D18to55_fsm : process(D55_READ_IN, buf_D55_DATAREADY_OUT, D18_READ_IN, D18_DATAREADY_IN, + D18to55_state, buf_D55_DATA_OUT, D18_DATA_IN) + variable dataisread18, dataisread55 : std_logic; + begin + next_D55_DATA_OUT <= buf_D55_DATA_OUT; + next_D18to55_state <= D18to55_state; + next_D18_READ_OUT <= '1'; + + if(D55_READ_IN = '1' AND buf_D55_DATAREADY_OUT = '1') then + dataisread55 := '1'; + else + dataisread55 := '0'; + end if; + + if(D18_READ_IN = '1' AND D18_DATAREADY_IN = '1') then + dataisread18 := '1'; + else + dataisread18 := '0'; + end if; + + if(dataisread55 = '1') then + next_D55_DATAREADY_OUT <= '0'; + else + next_D55_DATAREADY_OUT <= buf_D55_DATAREADY_OUT; + end if; + + + case D18to55_state is + when IDLE => + next_D18_READ_OUT <= '1'; + if(dataisread18 = '1') then + next_D55_DATA_OUT(55 downto 48) <= D18_DATA_IN(7 downto 0); + next_D18to55_state <= FIRST; + end if; + when FIRST => + if(dataisread18 = '1') then + next_D55_DATA_OUT(47 downto 32) <= D18_DATA_IN; + next_D18to55_state <= SECOND; + end if; + when SECOND => + if(dataisread18 = '1') then + next_D55_DATA_OUT(31 downto 16) <= D18_DATA_IN; + next_D18to55_state <= THIRD; + end if; + when THIRD => + if(dataisread18 = '1') then + next_D55_DATA_OUT(15 downto 0) <= D18_DATA_IN; + next_D55_DATAREADY_OUT <= '1'; + next_D18to55_state <= LAST; + next_D18_READ_OUT <= '0'; + end if; + when LAST => + if(dataisread55 = '1') then + next_D55_DATA_OUT <= (others => '0'); + next_D55_DATAREADY_OUT <= '0'; + next_D18to55_state <= IDLE; + else + next_D18_READ_OUT <= '0'; + end if; + end case; + end process; + + D18to55_fsm_reg : process(CLK, RESET) + begin + if RESET = '1' then + buf_D55_DATA_OUT <= (others => '0'); + D18to55_state <= IDLE; + buf_D55_DATAREADY_OUT <= '0'; + buf_D18_READ_OUT <= '0'; + elsif rising_edge(CLK) then + buf_D55_DATA_OUT <= next_D55_DATA_OUT; + D18to55_state <= next_D18to55_state; + buf_D55_DATAREADY_OUT <= next_D55_DATAREADY_OUT; + buf_D18_READ_OUT <= next_D18_READ_OUT; + else + buf_D55_DATA_OUT <= buf_D55_DATA_OUT; + D18to55_state <= D18to55_state; + buf_D55_DATAREADY_OUT <= buf_D55_DATAREADY_OUT; + buf_D18_READ_OUT <= buf_D18_READ_OUT; + end if; + end process; + +D55_DATA_OUT <= buf_D55_DATA_OUT; +D55_DATAREADY_OUT <= buf_D55_DATAREADY_OUT; +D18_READ_OUT <= buf_D18_READ_OUT; + +----------------------------------------------------------- +--Direction 55 to 18 +----------------------------------------------------------- + D55to18_fsm : process(buf_D18_DATA_OUT, buf_D18_PACKET_NUM_OUT, buf_D18_DATAREADY_OUT, + D18_READ_IN, D55_DATA_IN, D55_DATAREADY_IN, D55to18_state, + buf_D55_READ_OUT, buf_D55_DATA_IN) + variable dataisread : std_logic; + begin + next_D18_DATA_OUT <= buf_D18_DATA_OUT; + next_D18_PACKET_NUM_OUT <= buf_D18_PACKET_NUM_OUT; + next_D55to18_state <= D55to18_state; + next_D55_READ_OUT <= '0'; + next_buf_D55_DATA_IN <= buf_D55_DATA_IN; + + if(D18_READ_IN = '1' AND buf_D18_DATAREADY_OUT = '1') then + dataisread := '1'; + else + dataisread := '0'; + end if; + + + if(dataisread = '1') then + next_D18_DATAREADY_OUT <= '0'; + else + next_D18_DATAREADY_OUT <= buf_D18_DATAREADY_OUT; + end if; + + + case D55to18_state is + when IDLE => + next_D55_READ_OUT <= '1'; + if(D55_DATAREADY_IN = '1' AND buf_D55_READ_OUT = '1') then + next_buf_D55_DATA_IN(47 downto 0) <= D55_DATA_IN(47 downto 0); + next_D18_DATA_OUT(7 downto 0) <= D55_DATA_IN(55 downto 48); + next_D18_DATA_OUT(15 downto 8) <= (others => '0'); + next_D18_PACKET_NUM_OUT <= "00"; + next_D18_DATAREADY_OUT <= '1'; + next_D55to18_state <= FIRST; + end if; + when FIRST => + if(dataisread = '1') then + next_D18_DATA_OUT(15 downto 0) <= buf_D55_DATA_IN(47 downto 32); + next_D18_DATAREADY_OUT <= '1'; + next_D18_PACKET_NUM_OUT <= "01"; + next_D55to18_state <= SECOND; + end if; + when SECOND => + if(dataisread = '1') then + next_D18_DATA_OUT(15 downto 0) <= buf_D55_DATA_IN(31 downto 16); + next_D18_DATAREADY_OUT <= '1'; + next_D18_PACKET_NUM_OUT <= "10"; + next_D55to18_state <= THIRD; + end if; + when THIRD => + if(dataisread = '1') then + next_D18_DATA_OUT(15 downto 0) <= buf_D55_DATA_IN(15 downto 0); + next_D18_DATAREADY_OUT <= '1'; + next_D18_PACKET_NUM_OUT <= "11"; + next_D55to18_state <= LAST; + end if; + when LAST => + if(dataisread = '1') then + next_D18_DATA_OUT(15 downto 0) <= (others => '0'); + next_D18_DATAREADY_OUT <= '0'; + next_D55to18_state <= IDLE; + next_D18_PACKET_NUM_OUT <= "00"; + next_D55_READ_OUT <= '1'; + end if; + end case; + + end process; + + D55to18_fsm_reg : process(CLK, RESET) + begin + if RESET = '1' then + buf_D18_DATA_OUT <= (others => '0'); + buf_D55_DATA_IN <= (others => '0'); + buf_D55_READ_OUT <= '0'; + buf_D18_DATAREADY_OUT <= '0'; + buf_D18_PACKET_NUM_OUT <= "00"; + D55to18_state <= IDLE; + elsif rising_edge(CLK) then + buf_D18_DATA_OUT <= next_D18_DATA_OUT; + buf_D18_DATAREADY_OUT <= next_D18_DATAREADY_OUT; + buf_D55_READ_OUT <= next_D55_READ_OUT; + buf_D55_DATA_IN <= next_buf_D55_DATA_IN; + buf_D18_PACKET_NUM_OUT <= next_D18_PACKET_NUM_OUT; + D55to18_state <= next_D55to18_state; + else + buf_D18_DATA_OUT <= buf_D18_DATA_OUT; + buf_D18_DATAREADY_OUT <= buf_D18_DATAREADY_OUT; + buf_D55_READ_OUT <= buf_D55_READ_OUT; + buf_D55_DATA_IN <= buf_D55_DATA_IN; + buf_D18_PACKET_NUM_OUT <= buf_D18_PACKET_NUM_OUT; + D55to18_state <= D55to18_state; + end if; + end process; + +D18_DATA_OUT <= buf_D18_DATA_OUT; +D18_DATAREADY_OUT <= buf_D18_DATAREADY_OUT; +D18_PACKET_NUM_OUT <= buf_D18_PACKET_NUM_OUT; +D55_READ_OUT <= buf_D55_READ_OUT; + + +end architecture; \ No newline at end of file diff --git a/trb_net_fifo_16bit_bram_dualport.vhd b/trb_net_fifo_16bit_bram_dualport.vhd new file mode 100644 index 0000000..5321037 --- /dev/null +++ b/trb_net_fifo_16bit_bram_dualport.vhd @@ -0,0 +1,20 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +library unisim; +use UNISIM.VComponents.all; + + +entity trb_net_fifo_16bit_bram_dualport is + port (read_clock_in: IN std_logic; + write_clock_in: IN std_logic; + read_enable_in: IN std_logic; + write_enable_in: IN std_logic; + fifo_gsr_in: IN std_logic; + write_data_in: IN std_logic_vector(17 downto 0); + read_data_out: OUT std_logic_vector(17 downto 0); + full_out: OUT std_logic; + empty_out: OUT std_logic; + fifostatus_out: OUT std_logic_vector(3 downto 0) --counter for 1/16th of fifo + ); +end entity trb_net_fifo_16bit_bram_dualport; \ No newline at end of file diff --git a/trb_net_med_8bit_fast.vhd b/trb_net_med_8bit_fast.vhd new file mode 100644 index 0000000..81b20df --- /dev/null +++ b/trb_net_med_8bit_fast.vhd @@ -0,0 +1,503 @@ +--This entity provides data transfer of 55Bit in 4 16Bit packets via a 16Bit Bus +--with 8Bit data width plus 4 control Bits. +--data is repacked to have 8 spare Bits in the end of each word instead on the +--beginning. These Bits may be used for data integrity check later. +--CLK_LVDS is the clock used for transmission. Must be twice the normal CLK! + +------------------------------------------------- +--format on LVDS: 0-7 Data +-- 8-11 not used, maybe for debugging +-- 12 first packet indicator +-- 13 transmission clock +-- 14 transmission carrier +-- 15 transmission parity(0-7) +------------------------------------------------- + + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.STD_LOGIC_ARITH.ALL; +USE IEEE.STD_LOGIC_UNSIGNED.ALL; +library unisim; +use UNISIM.VComponents.all; +use work.trb_net_std.all; + +--Entity decalaration for clock generator +entity trb_net_med_8bit_fast is + port( + -- Misc + CLK : in std_logic; + CLK_LVDS : in std_logic; + RESET : in std_logic; + CLK_EN : in std_logic; + + -- 1st part: from the medium to the internal logic (trbnet) + INT_DATAREADY_OUT: out STD_LOGIC; + INT_DATA_OUT: out STD_LOGIC_VECTOR (15 downto 0); -- Data word + INT_PACKET_NR_OUT: out STD_LOGIC_VECTOR (1 downto 0); + INT_READ_IN: in STD_LOGIC; + INT_ERROR_OUT: out STD_LOGIC_VECTOR (2 downto 0); -- Status bits + + -- 2nd part: from the internal logic (trbnet) to the medium + INT_DATAREADY_IN: in STD_LOGIC; -- Data word is offered for the Media + INT_DATA_IN: in STD_LOGIC_VECTOR (15 downto 0); -- Data word + INT_PACKET_NR_IN: in STD_LOGIC_VECTOR (1 downto 0); + INT_READ_OUT: out STD_LOGIC; -- offered word is read + INT_ERROR_IN: in STD_LOGIC_VECTOR (2 downto 0); -- Status bits + + -- Media direction port + -- in this case for the cable => 32 lines in total + MED_DATA_OUT: out STD_LOGIC_VECTOR (12 downto 0); -- Data word + MED_TRANSMISSION_CLK_OUT: out STD_LOGIC; + MED_CARRIER_OUT: out STD_LOGIC; + MED_PARITY_OUT: out STD_LOGIC; + MED_DATA_IN: in STD_LOGIC_VECTOR (12 downto 0); -- Data word + MED_TRANSMISSION_CLK_IN: in STD_LOGIC; + MED_CARRIER_IN: in STD_LOGIC; + MED_PARITY_IN: in STD_LOGIC; + + -- Status and control port => this never can hurt + STAT: out STD_LOGIC_VECTOR (31 downto 0); + --STAT(0): Busy reading from media + --STAT(1): Busy writing to media + --STAT(31 downto 28): packets_in (mod 16) + --STAT(27 downto 24): packets_out (mod 16) + --STAT(11 downto 8): INT2MED state + --STAT(15 downto 12): MED2INT state + + CTRL: in STD_LOGIC_VECTOR (31 downto 0) + --CTRL(24..31) -> lvds-data(63 downto 56) via lvds + --once for each packet + + ); +end entity; + +architecture trb_net_med_8bit_fast_arch of trb_net_med_8bit_fast is + +component trb_net_fifo_16bit_bram_dualport + port (read_clock_in: IN std_logic; + write_clock_in: IN std_logic; + read_enable_in: IN std_logic; + write_enable_in: IN std_logic; + fifo_gsr_in: IN std_logic; --reset + write_data_in: IN std_logic_vector(17 downto 0); + read_data_out: OUT std_logic_vector(17 downto 0); + full_out: OUT std_logic; + empty_out: OUT std_logic; + fifostatus_out: OUT std_logic_vector(3 downto 0) + ); +end component trb_net_fifo_16bit_bram_dualport; + + +component trb_net_18_to_16_converter + generic ( VERSION : integer := 1); --Version of included sbufs + port( + -- Misc + CLK : in std_logic; + RESET : in std_logic; + CLK_EN : in std_logic; + + D18_DATAREADY_IN: in STD_LOGIC; + D18_PACKET_NUM_IN: in STD_LOGIC_VECTOR(1 downto 0); + D18_DATA_IN: in STD_LOGIC_VECTOR (15 downto 0); -- Data word + D18_READ_OUT: out STD_LOGIC; + + D16_DATAREADY_OUT: out STD_LOGIC; + D16_DATA_OUT: out STD_LOGIC_VECTOR (15 downto 0); -- Data word + D16_READ_IN: in STD_LOGIC; + D16_PACKET_NUM_OUT: out STD_LOGIC_VECTOR(1 downto 0); + + D18_DATAREADY_OUT: out STD_LOGIC; + D18_PACKET_NUM_OUT: out STD_LOGIC_VECTOR(1 downto 0); + D18_DATA_OUT: out STD_LOGIC_VECTOR (15 downto 0); -- Data word + D18_READ_IN: in STD_LOGIC; + + D16_DATAREADY_IN: in STD_LOGIC; + D16_DATA_IN: in STD_LOGIC_VECTOR (15 downto 0); -- Data word + D16_READ_OUT: out STD_LOGIC; + D16_PACKET_NUM_IN: in STD_LOGIC_VECTOR(1 downto 0) + ); +end component; + + +signal CLK_TRANS : std_logic; +signal fifo_data_in, next_fifo_data_in : std_logic_vector(17 downto 0); +signal next_next_fifo_data_in, buf_next_fifo_data_in : std_logic_vector(7 downto 0); +signal fifo_data_out : std_logic_vector(17 downto 0); +signal fifo_full_out, fifo_empty_out : std_logic; +signal fifo_status_out : std_logic_vector(3 downto 0); +signal fifo_write_enable, next_fifo_write_enable : std_logic; +signal fifo_read_enable, last_fifo_read_enable : std_logic; +--signal fifo_data_buffer : std_logic_vector(15 downto 0); +signal next_packet_in_state, packet_in_state : std_logic; + + +signal buf_MED_PARITY_IN, buf_MED_CARRIER_IN : std_logic; +signal buf_MED_DATA_IN : std_logic_vector(12 downto 0); +signal buf_med_transmission_clk_in : std_logic; +signal buf_MED_PARITY_OUT, next_MED_PARITY_OUT : std_logic; +signal buf_MED_CARRIER_OUT, next_MED_CARRIER_OUT : std_logic; +signal buf_MED_TRANSMISSION_CLK_OUT, next_MED_TRANSMISSION_CLK_OUT : std_logic; +signal buf_MED_DATA_OUT, next_MED_DATA_OUT : std_logic_vector(12 downto 0); + +signal data_valid, next_data_valid : std_logic; +--signal next_recv_data, recv_data : std_logic_vector(15 downto 0); + +signal next_INT_DATA_OUT, buf_INT_DATA_OUT : std_logic_vector(15 downto 0); +signal next_INT_DATAREADY_OUT, buf_INT_DATAREADY_OUT : std_logic; +signal next_int_packet_nr_out, buf_int_packet_nr_out : std_logic_vector(1 downto 0); +signal buf_INT_READ_OUT : std_logic; +signal next_send_data_byte1, send_data_byte1 : std_logic_vector(7 downto 0); +signal next_send_data_byte2, send_data_byte2 : std_logic_vector(7 downto 0); +signal next_send_data_byte1_parity, send_data_byte1_parity : std_logic; +signal next_send_data_byte2_parity, send_data_byte2_parity : std_logic; +signal next_send_dataready, send_dataready : std_logic; +signal next_send_dataready1, send_dataready1 : std_logic; +signal next_send_packet1, send_packet1 : std_logic; +signal next_fifo_data_ready, fifo_data_ready : std_logic; +signal next_earlier_fifo_data_ready, earlier_fifo_data_ready : std_logic; + +--signal recv_state, next_recv_state : std_logic_vector(1 downto 0); + +signal validbit, next_validbit : std_logic; +signal buf_int_error_out, next_INT_ERROR_OUT : std_logic_vector(2 downto 0); + +signal CONV_DATAREADY_OUT : std_logic; +signal CONV_DATA_OUT : std_logic_vector(15 downto 0); +signal CONV_READ_IN: std_logic; +signal CONV_PACKET_NR_IN, CONV_PACKET_NR_OUT: std_logic_vector(1 downto 0); + +begin + +----------------------------------------------------------------------- +-- Fifo for incoming data +----------------------------------------------------------------------- + LVDS_FIFO1 : trb_net_fifo_16bit_bram_dualport + port map( + read_clock_in => CLK, + write_clock_in => CLK_TRANS, + read_enable_in => fifo_read_enable, + write_enable_in => fifo_write_enable, + fifo_gsr_in => RESET, + write_data_in => fifo_data_in, + read_data_out => fifo_data_out, + full_out => fifo_full_out, + empty_out => fifo_empty_out, + fifostatus_out => fifo_status_out + ); + + + +CONV16to18 : trb_net_18_to_16_converter + generic map( + VERSION => 0 + ) + port map( + -- Misc + CLK => CLK, + RESET => RESET, + CLK_EN => CLK_EN, + + D18_DATAREADY_IN => INT_DATAREADY_IN, + D18_PACKET_NUM_IN => INT_PACKET_NR_IN, + D18_DATA_IN => INT_DATA_IN, + D18_READ_OUT => INT_READ_OUT, + + D16_DATAREADY_OUT => CONV_DATAREADY_OUT, + D16_DATA_OUT => CONV_DATA_OUT, + D16_READ_IN => CONV_READ_IN, + D16_PACKET_NUM_OUT => CONV_PACKET_NR_OUT, + + D18_DATAREADY_OUT => open, + D18_PACKET_NUM_OUT => open, + D18_DATA_OUT => open, + D18_READ_IN => '0', + + D16_DATAREADY_IN => '0', + D16_DATA_IN => (others => '0'), + D16_READ_OUT => open, + D16_PACKET_NUM_IN => "00" + ); + + + +----------------------------------------------------------------------- +-- Getting clock from LVDS +----------------------------------------------------------------------- + + buf_med_transmission_clk_in <= MED_TRANSMISSION_CLK_IN; + -- BUFG Instantiation for CLKFX + U0_BUFG: BUFG + port map ( + I => buf_MED_TRANSMISSION_CLK_IN, + O => CLK_TRANS + ); + + +----------------------------------------------------------------------- +-- Preparing incoming data for fifo +----------------------------------------------------------------------- + + + +--BUG: No parity check for last part of packet, failure is passed to next packet! + + recv : process(packet_in_state, buf_next_fifo_data_in, buf_MED_DATA_IN, buf_MED_CARRIER_IN, buf_MED_PARITY_IN, data_valid) + --variable data_valid : std_logic; + begin + next_data_valid <= buf_MED_PARITY_IN xnor xor_all(buf_MED_DATA_IN(7 downto 0)); + next_fifo_write_enable <= buf_MED_CARRIER_IN AND NOT packet_in_state; + next_next_fifo_data_in <= (others => '0'); + next_fifo_data_in(17) <= data_valid; + next_fifo_data_in(16) <= buf_MED_DATA_IN(12); + next_fifo_data_in(7 downto 0) <= (others => '0'); + next_fifo_data_in(15 downto 8) <= buf_next_fifo_data_in(7 downto 0); + next_packet_in_state <= packet_in_state; + + if buf_MED_CARRIER_IN = '1' then + next_packet_in_state <= not packet_in_state; + if packet_in_state ='0' then + next_fifo_data_in(7 downto 0) <= buf_MED_data_in(7 downto 0); + else + next_next_fifo_data_in(7 downto 0) <= buf_MED_data_in(7 downto 0); + end if; + end if; + end process; + + recv_reg : process(CLK_TRANS, RESET) + begin + if RESET = '1' then + fifo_write_enable <= '0'; + --data_valid <= '0'; + fifo_data_in <= (others => '0'); + --buf_next_fifo_data_in <= (others => '0'); + packet_in_state <= '0'; + elsif rising_edge(CLK_TRANS) then + data_valid <= next_data_valid; + fifo_write_enable <= next_fifo_write_enable; + fifo_data_in <= next_fifo_data_in; + buf_next_fifo_data_in <= next_next_fifo_data_in; + packet_in_state <= next_packet_in_state; + else + data_valid <= data_valid; + fifo_write_enable <= fifo_write_enable; + fifo_data_in <= fifo_data_in; + buf_next_fifo_data_in <= buf_next_fifo_data_in; + packet_in_state <= packet_in_state; + end if; + end process; + +----------------------------------------------------------------------- +-- Reading data from LVDS +----------------------------------------------------------------------- +-- +-- +-- -- buf_MED_PARITY_IN <= MED_PARITY_IN; +-- -- buf_MED_CARRIER_IN <= MED_CARRIER_IN; +-- -- buf_MED_DATA_IN <= MED_DATA_IN; +-- + + lvds_reg : process(CLK_TRANS, RESET) + begin + if RESET = '1' then + buf_MED_CARRIER_IN <= '0'; + buf_MED_PARITY_IN <= '0'; + buf_MED_DATA_IN(11 downto 0) <= (others => '0'); --12 is part of a shift register! + elsif rising_edge(CLK_TRANS) then + buf_MED_CARRIER_IN <= MED_CARRIER_IN; + buf_MED_PARITY_IN <= MED_PARITY_IN; + buf_MED_DATA_IN <= MED_DATA_IN; + else + buf_MED_CARRIER_IN <= buf_MED_CARRIER_IN; + buf_MED_PARITY_IN <= buf_MED_PARITY_IN; + buf_MED_DATA_IN <= buf_MED_DATA_IN; + end if; + end process; + + + +----------------------------------------------------------------------- +-- Reading data from fifo, offering to INT +----------------------------------------------------------------------- + + process(fifo_empty_out, INT_READ_IN, buf_INT_DATAREADY_OUT, last_fifo_read_enable, + fifo_data_out, buf_int_packet_nr_out, fifo_data_ready) + begin + fifo_read_enable <= (not fifo_empty_out) + and ((buf_int_dataready_out and int_read_in) or not buf_int_dataready_out); + --set when fifo is not empty and available data is read or no data available + next_int_dataready_out <= buf_int_dataready_out; + next_int_data_out <= (others => '0'); + next_int_packet_nr_out <= buf_int_packet_nr_out; + next_fifo_data_ready <= (not fifo_empty_out + and ((buf_int_dataready_out and int_read_in) or not buf_int_dataready_out)) + or (fifo_data_ready and buf_int_dataready_out and not int_read_in); + --data will be available when read_enable is set or when it was set before and + --data is not read now + + if (buf_int_dataready_out = '1' and int_read_in = '1') then + next_int_dataready_out <= '0'; + end if; + + if last_fifo_read_enable = '1' and fifo_data_out(16) = '1' then + next_int_packet_nr_out <= "00"; + elsif last_fifo_read_enable = '1' then + next_int_packet_nr_out <= buf_int_packet_nr_out + 1; + else + next_int_packet_nr_out <= buf_int_packet_nr_out; + end if; + + + if fifo_data_ready = '1' then + next_int_data_out <= fifo_data_out(15 downto 0); + next_int_dataready_out <= '1'; + + if fifo_data_out(17) = '0' then + next_int_error_out <= ERROR_FATAL; + else + next_int_error_out <= ERROR_OK; + end if; + if fifo_data_out(16) = '1' and buf_int_packet_nr_out /= "11" then + next_int_error_out <= ERROR_ENCOD; + end if; + end if; + + end process; + + process(CLK,RESET) + begin + if RESET = '1' then + last_fifo_read_enable <= '0'; + buf_int_data_out <= (others => '0'); + buf_int_dataready_out <= '0'; + buf_int_error_out <= ERROR_NC; + buf_int_packet_nr_out <= "00"; + fifo_data_ready <= '0'; + elsif rising_edge(CLK) then + last_fifo_read_enable <= fifo_read_enable; + buf_int_data_out <= next_int_data_out; + buf_int_dataready_out <= next_int_dataready_out; + buf_int_error_out <= next_int_error_out; + buf_int_packet_nr_out <= next_int_packet_nr_out; + fifo_data_ready <= next_fifo_data_ready; + else + last_fifo_read_enable <= last_fifo_read_enable; + buf_int_data_out <= buf_int_data_out; + buf_int_dataready_out <= buf_int_dataready_out; + buf_int_error_out <= buf_int_error_out; + buf_int_packet_nr_out <= buf_int_packet_nr_out; + fifo_data_ready <= fifo_data_ready; + end if; + end process; + + +INT_DATA_OUT <= buf_int_data_out; +INT_DATAREADY_OUT <= buf_INT_DATAREADY_OUT; +INT_PACKET_NR_OUT <= buf_int_packet_nr_out; + + +----------------------------------------------------------------------- +-- Sending data +----------------------------------------------------------------------- + +CONV_READ_IN <= '1'; + + process(CONV_DATAREADY_OUT, CONV_DATA_OUT, CONV_PACKET_NR_OUT, CONV_READ_IN, + send_data_byte1, send_data_byte2, send_packet1) + begin + + next_send_dataready <= '0'; + next_send_data_byte1 <= send_data_byte1; + next_send_data_byte2 <= send_data_byte2; + next_send_data_byte1_parity <= '0'; + next_send_data_byte2_parity <= '0'; + next_send_packet1 <= '0'; + if CONV_DATAREADY_OUT = '1' and CONV_READ_IN = '1' then + if CONV_PACKET_NR_OUT = "00" and send_packet1 = '0' then + next_send_packet1 <= '1'; + else + next_send_packet1 <= '0'; + end if; + next_send_data_byte1 <= CONV_DATA_OUT(15 downto 8); + next_send_data_byte2 <= CONV_DATA_OUT(7 downto 0); + next_send_dataready <= '1'; + next_send_data_byte2_parity <= xor_all(CONV_DATA_OUT(7 downto 0)); + next_send_data_byte1_parity <= xor_all(CONV_DATA_OUT(15 downto 8)); + end if; + end process; + + process(CLK, RESET) + begin + if RESET = '1' then + send_data_byte1 <= (others => '0'); + send_data_byte2 <= (others => '0'); + send_data_byte1_parity <= '0'; + send_data_byte2_parity <= '0'; + send_dataready <= '0'; + send_packet1 <= '0'; + elsif rising_edge(CLK) then + send_data_byte1 <= next_send_data_byte1; + send_data_byte2 <= next_send_data_byte2; + send_data_byte1_parity <= next_send_data_byte1_parity; + send_data_byte2_parity <= next_send_data_byte2_parity; + send_dataready <= next_send_dataready; + send_packet1 <= next_send_packet1; + else + send_data_byte1 <= send_data_byte1; + send_data_byte2 <= send_data_byte2; + send_data_byte1_parity <= send_data_byte1_parity; + send_data_byte2_parity <= send_data_byte2_parity; + send_dataready <= send_dataready; + send_packet1 <= send_packet1; + end if; + end process; + + process(send_dataready, send_data_byte1, send_data_byte2, + send_dataready1, send_data_byte1_parity, send_data_byte2_parity, send_packet1) + begin + next_MED_DATA_OUT(11 downto 8) <= (others => '0'); + next_MED_DATA_OUT(12) <= send_packet1; + next_MED_DATA_OUT(7 downto 0) <= (others => '0'); + next_MED_CARRIER_OUT <= '0'; + next_MED_PARITY_OUT <= '0'; + next_send_dataready1 <= '0'; + if send_dataready = '1' and send_dataready1 = '0' then + next_MED_DATA_OUT(7 downto 0) <= send_data_byte1; + next_MED_PARITY_OUT <= send_data_byte1_parity; + next_MED_CARRIER_OUT <= '1'; + next_send_dataready1 <= '1'; + + elsif send_dataready1 = '1' then + next_MED_DATA_OUT(7 downto 0) <= send_data_byte2; + next_MED_PARITY_OUT <= send_data_byte2_parity; + next_MED_CARRIER_OUT <= '1'; + end if; + end process; + + process(CLK_LVDS, RESET) + begin + if RESET = '1' then + buf_MED_DATA_OUT <= (others => '0'); + buf_MED_CARRIER_OUT <= '0'; + buf_MED_PARITY_OUT <= '0'; + send_dataready1 <= '0'; + elsif rising_edge(CLK_LVDS) then + buf_MED_DATA_OUT <= next_MED_DATA_OUT; + buf_MED_CARRIER_OUT <= next_MED_CARRIER_OUT; + buf_MED_PARITY_OUT <= next_MED_PARITY_OUT; + send_dataready1 <= next_send_dataready1; + else + buf_MED_DATA_OUT <= buf_MED_DATA_OUT; + buf_MED_CARRIER_OUT <= buf_MED_CARRIER_OUT; + buf_MED_PARITY_OUT <= buf_MED_PARITY_OUT; + send_dataready1 <= send_dataready1; + end if; + end process; + +MED_PARITY_OUT <= buf_MED_PARITY_OUT; +MED_CARRIER_OUT <= buf_MED_CARRIER_OUT; +MED_TRANSMISSION_CLK_OUT <= not CLK_LVDS; +MED_DATA_OUT <= buf_MED_DATA_OUT; + +end architecture; + diff --git a/xilinx/trb_net_fifo_16bit_bram_dualport_arch.vhd b/xilinx/trb_net_fifo_16bit_bram_dualport_arch.vhd new file mode 100644 index 0000000..fa43ecf --- /dev/null +++ b/xilinx/trb_net_fifo_16bit_bram_dualport_arch.vhd @@ -0,0 +1,513 @@ +--Taken from Xilinx Application note 258 and modified to size 511x18 + + +--------------------------------------------------------------------------- +-- -- +-- Module : fifoctlr_ic_v2.vhd Last Update: 07/14/00 -- +-- -- +-- Description : FIFO controller top level. -- +-- Implements a 511x36 FIFO with independent read/write -- +-- clocks. -- +-- -- +-- The following VHDL code implements a 511x36 FIFO in a Virtex -- +-- device. The inputs are a Read Clock and Read Enable, a Write Clock -- +-- and Write Enable, Write Data, and a FIFO_gsr signal as an initial -- +-- reset. The outputs are Read Data, Full, Empty, and the FIFOstatus -- +-- outputs, which indicate roughly how full the FIFO is. -- +-- -- +-- Designer : Nick Camilleri -- +-- -- +-- Company : Xilinx, Inc. -- +-- -- +-- Disclaimer : THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY -- +-- WHATSOEVER AND XILINX SPECIFICALLY DISCLAIMS ANY -- +-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR -- +-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. -- +-- THEY ARE ONLY INTendED TO BE USED BY XILINX -- +-- CUSTOMERS, AND WITHIN XILINX DEVICES. -- +-- -- +-- Copyright (c) 2000 Xilinx, Inc. -- +-- All rights reserved -- +-- -- +--------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +library unisim; +use UNISIM.VComponents.all; + + + + +architecture trb_net_fifo_16bit_bram_dualport_arch of trb_net_fifo_16bit_bram_dualport is + signal read_clock: std_logic; + signal write_clock: std_logic; + signal read_enable: std_logic; + signal write_enable: std_logic; + signal fifo_gsr: std_logic; + signal read_data: std_logic_vector(17 downto 0); + signal write_data: std_logic_vector(17 downto 0); + signal full: std_logic; + signal empty: std_logic; + signal read_addr: std_logic_vector(9 downto 0); + signal read_addrgray: std_logic_vector(8 downto 0); + signal read_nextgray: std_logic_vector(8 downto 0); + signal read_lastgray: std_logic_vector(8 downto 0); + signal write_addr: std_logic_vector(9 downto 0); + signal write_addrgray: std_logic_vector(8 downto 0); + signal write_nextgray: std_logic_vector(8 downto 0); + signal fifostatus: std_logic_vector(8 downto 0); + signal read_allow: std_logic; + signal write_allow: std_logic; + signal empty_allow: std_logic; + signal full_allow: std_logic; + signal ecomp: std_logic_vector(8 downto 0); + signal fcomp: std_logic_vector(8 downto 0); + signal emuxcyo: std_logic_vector(8 downto 0); + signal fmuxcyo: std_logic_vector(8 downto 0); + signal emptyg: std_logic; + signal fullg: std_logic; + signal read_truegray: std_logic_vector(8 downto 0); + signal rag_writesync: std_logic_vector(8 downto 0); + signal ra_writesync: std_logic_vector(8 downto 0); + signal write_addrr: std_logic_vector(8 downto 0); + signal xorout: std_logic_vector(1 downto 0); + signal gnd_bus: std_logic_vector(17 downto 0); + signal gnd: std_logic; + signal pwr: std_logic; + +component BUFG + port ( + I: IN std_logic; + O: OUT std_logic); +end component; + +component MUXCY_L + port ( + DI: IN std_logic; + CI: IN std_logic; + S: IN std_logic; + LO: OUT std_logic); +end component; + +component RAMB16_S18_S18 + port ( + ADDRA: IN std_logic_vector(9 downto 0); + ADDRB: IN std_logic_vector(9 downto 0); + DIA: IN std_logic_vector(15 downto 0); + DIB: IN std_logic_vector(15 downto 0); + DIPA: IN std_logic_vector(1 downto 0); + DIPB: IN std_logic_vector(1 downto 0); + WEA: IN std_logic; + WEB: IN std_logic; + CLKA: IN std_logic; + CLKB: IN std_logic; + SSRA: IN std_logic; + SSRB: IN std_logic; + ENA: IN std_logic; + ENB: IN std_logic; + DOA: OUT std_logic_vector(15 downto 0); + DOB: OUT std_logic_vector(15 downto 0); + DOPA: OUT std_logic_vector(1 downto 0); + DOPB: OUT std_logic_vector(1 downto 0)); +end component; + +BEGIN + read_enable <= read_enable_in; + write_enable <= write_enable_in; + fifo_gsr <= fifo_gsr_in; + write_data <= write_data_in; + read_data_out <= read_data; + full_out <= full; + empty_out <= empty; + fifostatus_out <= fifostatus(8 downto 5); + gnd_bus <= "000000000000000000"; + gnd <= '0'; + pwr <= '1'; + + read_addr(9) <= '0'; + write_addr(9) <= '0'; + + +-------------------------------------------------------------------------- +-- -- +-- Global input clock buffers are instantianted for both the read_clock -- +-- and the write_clock, to avoid skew problems. -- +-- -- +-------------------------------------------------------------------------- +read_clock <= read_clock_in; +write_clock <= write_clock_in; +--gclk1: BUFG port map (I => read_clock_in, O => read_clock); +--gclk2: BUFG port map (I => write_clock_in, O => write_clock); + +-------------------------------------------------------------------------- +-- -- +-- Block RAM instantiation for FIFO. Module is 512x18, of which one -- +-- address location is sacrificed for the overall speed of the design. -- +-- -- +-------------------------------------------------------------------------- + +bram1: RAMB16_S18_S18 port map (ADDRA => read_addr, ADDRB => write_addr, + DIA => gnd_bus(15 downto 0), DIPA => gnd_bus(17 downto 16), + DIB => write_data(15 downto 0), DIPB => write_data(17 downto 16), + WEA => gnd, WEB => pwr, CLKA => read_clock, CLKB => write_clock, + SSRA => gnd, SSRB => gnd, ENA => read_allow, ENB => write_allow, + DOA => read_data(15 downto 0), DOPA => read_data(17 downto 16) ); + +---------------------------------------------------------------- +-- -- +-- Allow flags determine whether FIFO control logic can -- +-- operate. If read_enable is driven high, and the FIFO is -- +-- not Empty, then Reads are allowed. Similarly, if the -- +-- write_enable signal is high, and the FIFO is not Full, -- +-- then Writes are allowed. -- +-- -- +---------------------------------------------------------------- + +read_allow <= (read_enable AND NOT empty); +write_allow <= (write_enable AND NOT full); + +full_allow <= (full OR write_enable); +empty_allow <= (empty OR read_enable); + +--------------------------------------------------------------- +-- -- +-- Empty flag is set on fifo_gsr (initial), or when gray -- +-- code counters are equal, or when there is one word in -- +-- the FIFO, and a Read operation is about to be performed. -- +-- -- +--------------------------------------------------------------- + +proc1: PROCESS (read_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + empty <= '1'; + ELSIF (read_clock'EVENT AND read_clock = '1') THEN + IF (empty_allow = '1') THEN + empty <= emptyg; + end IF; + end IF; +end PROCESS proc1; + +--------------------------------------------------------------- +-- -- +-- Full flag is set on fifo_gsr (initial, but it is cleared -- +-- on the first valid write_clock edge after fifo_gsr is -- +-- de-asserted), or when Gray-code counters are one away -- +-- from being equal (the Write Gray-code address is equal -- +-- to the Last Read Gray-code address), or when the Next -- +-- Write Gray-code address is equal to the Last Read Gray- -- +-- code address, and a Write operation is about to be -- +-- performed. -- +-- -- +--------------------------------------------------------------- + +proc2: PROCESS (write_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + full <= '1'; + ELSIF (write_clock'EVENT AND write_clock = '1') THEN + IF (full_allow = '1') THEN + full <= fullg; + end IF; + end IF; +end PROCESS proc2; + +---------------------------------------------------------------- +-- -- +-- Generation of Read address pointers. The primary one is -- +-- binary (read_addr), and the Gray-code derivatives are -- +-- generated via pipelining the binary-to-Gray-code result. -- +-- The initial values are important, so they're in sequence. -- +-- -- +-- Grey-code addresses are used so that the registered -- +-- Full and Empty flags are always clean, and never in an -- +-- unknown state due to the asynchonous relationship of the -- +-- Read and Write clocks. In the worst case scenario, Full -- +-- and Empty would simply stay active one cycle longer, but -- +-- it would not generate an error or give false values. -- +-- -- +---------------------------------------------------------------- + +proc3: PROCESS (read_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + read_addr(8 downto 0) <= "000000000"; + ELSIF (read_clock'EVENT AND read_clock = '1') THEN + IF (read_allow = '1') THEN + read_addr(8 downto 0) <= read_addr(8 downto 0) + 1; + end IF; + end IF; +end PROCESS proc3; + +proc4: PROCESS (read_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + read_nextgray <= "100000000"; + ELSIF (read_clock'EVENT AND read_clock = '1') THEN + IF (read_allow = '1') THEN + read_nextgray(8) <= read_addr(8); + read_nextgray(7) <= read_addr(8) XOR read_addr(7); + read_nextgray(6) <= read_addr(7) XOR read_addr(6); + read_nextgray(5) <= read_addr(6) XOR read_addr(5); + read_nextgray(4) <= read_addr(5) XOR read_addr(4); + read_nextgray(3) <= read_addr(4) XOR read_addr(3); + read_nextgray(2) <= read_addr(3) XOR read_addr(2); + read_nextgray(1) <= read_addr(2) XOR read_addr(1); + read_nextgray(0) <= read_addr(1) XOR read_addr(0); + end IF; + end IF; +end PROCESS proc4; + +proc5: PROCESS (read_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + read_addrgray <= "100000001"; + ELSIF (read_clock'EVENT AND read_clock = '1') THEN + IF (read_allow = '1') THEN + read_addrgray <= read_nextgray; + end IF; + end IF; +end PROCESS proc5; + +proc6: PROCESS (read_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + read_lastgray <= "100000011"; + ELSIF (read_clock'EVENT AND read_clock = '1') THEN + IF (read_allow = '1') THEN + read_lastgray <= read_addrgray; + end IF; + end IF; +end PROCESS proc6; + +---------------------------------------------------------------- +-- -- +-- Generation of Write address pointers. Identical copy of -- +-- read pointer generation above, except for names. -- +-- -- +---------------------------------------------------------------- + +proc7: PROCESS (write_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + write_addr(8 downto 0) <= "000000000"; + ELSIF (write_clock'EVENT AND write_clock = '1') THEN + IF (write_allow = '1') THEN + write_addr(8 downto 0) <= write_addr(8 downto 0) + 1; + end IF; + end IF; +end PROCESS proc7; + +proc8: PROCESS (write_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + write_nextgray <= "100000000"; + ELSIF (write_clock'EVENT AND write_clock = '1') THEN + IF (write_allow = '1') THEN + write_nextgray(8) <= write_addr(8); + write_nextgray(7) <= write_addr(8) XOR write_addr(7); + write_nextgray(6) <= write_addr(7) XOR write_addr(6); + write_nextgray(5) <= write_addr(6) XOR write_addr(5); + write_nextgray(4) <= write_addr(5) XOR write_addr(4); + write_nextgray(3) <= write_addr(4) XOR write_addr(3); + write_nextgray(2) <= write_addr(3) XOR write_addr(2); + write_nextgray(1) <= write_addr(2) XOR write_addr(1); + write_nextgray(0) <= write_addr(1) XOR write_addr(0); + end IF; + end IF; +end PROCESS proc8; + +proc9: PROCESS (write_clock, fifo_gsr) +BEGIN + IF (fifo_gsr = '1') THEN + write_addrgray <= "100000001"; + ELSIF (write_clock'EVENT AND write_clock = '1') THEN + IF (write_allow = '1') THEN + write_addrgray <= write_nextgray; + end IF; + end IF; +end PROCESS proc9; + +---------------------------------------------------------------- +-- -- +-- Alternative generation of FIFOstatus outputs. Used to -- +-- determine how full FIFO is, based on how far the Write -- +-- pointer is ahead of the Read pointer. read_truegray -- +-- is synchronized to write_clock (rag_writesync), converted -- +-- to binary (ra_writesync), and then subtracted from the -- +-- pipelined write_addr (write_addrr) to find out how many -- +-- words are in the FIFO (fifostatus). The top bits are -- +-- then 1/2 full, 1/4 full, etc. (not mutually exclusive). -- +-- fifostatus has a one-cycle latency on write_clock; or, -- +-- one cycle after the write address is incremented on a -- +-- write operation, fifostatus is updated with the new -- +-- capacity information. There is a two-cycle latency on -- +-- read operations. -- +-- -- +-- If read_clock is much faster than write_clock, it is -- +-- possible that the fifostatus counter could drop several -- +-- positions in one write_clock cycle, so the low-order bits -- +-- of fifostatus are not as reliable. -- +-- -- +-- NOTE: If the fifostatus flags are not needed, then this -- +-- section of logic can be trimmed, saving 20+ slices and -- +-- improving the circuit performance. -- +-- -- +---------------------------------------------------------------- + +-- proc10: PROCESS (read_clock, fifo_gsr) +-- BEGIN +-- IF (fifo_gsr = '1') THEN +-- read_truegray <= "000000000"; +-- ELSIF (read_clock'EVENT AND read_clock = '1') THEN +-- read_truegray(8) <= read_addr(8); +-- read_truegray(7) <= read_addr(8) XOR read_addr(7); +-- read_truegray(6) <= read_addr(7) XOR read_addr(6); +-- read_truegray(5) <= read_addr(6) XOR read_addr(5); +-- read_truegray(4) <= read_addr(5) XOR read_addr(4); +-- read_truegray(3) <= read_addr(4) XOR read_addr(3); +-- read_truegray(2) <= read_addr(3) XOR read_addr(2); +-- read_truegray(1) <= read_addr(2) XOR read_addr(1); +-- read_truegray(0) <= read_addr(1) XOR read_addr(0); +-- end IF; +-- end PROCESS proc10; +-- +-- proc11: PROCESS (write_clock, fifo_gsr) +-- BEGIN +-- IF (fifo_gsr = '1') THEN +-- rag_writesync <= "000000000"; +-- ELSIF (write_clock'EVENT AND write_clock = '1') THEN +-- rag_writesync <= read_truegray; +-- end IF; +-- end PROCESS proc11; +-- +-- xorout(0) <= (rag_writesync(8) XOR rag_writesync(7) XOR rag_writesync(6) XOR +-- rag_writesync(5)); +-- xorout(1) <= (rag_writesync(4) XOR rag_writesync(3) XOR rag_writesync(2) XOR +-- rag_writesync(1)); +-- +-- ra_writesync(8) <= rag_writesync(8); +-- ra_writesync(7) <= (rag_writesync(8) XOR rag_writesync(7)); +-- ra_writesync(6) <= (rag_writesync(8) XOR rag_writesync(7) XOR rag_writesync(6)); +-- ra_writesync(5) <= xorout(0); +-- ra_writesync(4) <= (xorout(0) XOR rag_writesync(4)); +-- ra_writesync(3) <= (xorout(0) XOR rag_writesync(4) XOR rag_writesync(3)); +-- ra_writesync(2) <= (xorout(0) XOR rag_writesync(4) XOR rag_writesync(3) +-- XOR rag_writesync(2)); +-- ra_writesync(1) <= (xorout(0) XOR xorout(1)); +-- ra_writesync(0) <= (xorout(0) XOR xorout(1) XOR rag_writesync(0)); +-- +-- proc12: PROCESS (write_clock, fifo_gsr) +-- BEGIN +-- IF (fifo_gsr = '1') THEN +-- write_addrr <= "000000000"; +-- ELSIF (write_clock'EVENT AND write_clock = '1') THEN +-- write_addrr <= write_addr(8 downto 0); +-- end IF; +-- end PROCESS proc12; +-- +-- proc13: PROCESS (write_clock, fifo_gsr) +-- BEGIN +-- IF (fifo_gsr = '1') THEN +-- fifostatus <= "000000000"; +-- ELSIF (write_clock'EVENT AND write_clock = '1') THEN +-- IF (full = '0') THEN +-- fifostatus <= (write_addrr - ra_writesync); +-- end IF; +-- end IF; +-- end PROCESS proc13; + +---------------------------------------------------------------- +-- -- +-- The two conditions decoded with special carry logic are -- +-- Empty and Full (gated versions). These are used to -- +-- determine the next state of the Full/Empty flags. Carry -- +-- logic is used for optimal speed. (The previous -- +-- implementation of AlmostEmpty and AlmostFull have been -- +-- wrapped into the corresponding carry chains for faster -- +-- performance). -- +-- -- +-- When write_addrgray is equal to read_addrgray, the FIFO -- +-- is Empty, and emptyg (combinatorial) is asserted. Or, -- +-- when write_addrgray is equal to read_nextgray (1 word in -- +-- the FIFO) then the FIFO potentially could be going Empty, -- +-- so emptyg is asserted, and the Empty flip-flop enable is -- +-- gated with empty_allow, which is conditioned with a valid -- +-- read. -- +-- -- +-- Similarly, when read_lastgray is equal to write_addrgray, -- +-- the FIFO is full (511 addresses). Or, when read_lastgray -- +-- is equal to write_nextgray, then the FIFO potentially -- +-- could be going Full, so fullg is asserted, and the Full -- +-- flip-flop enable is gated with full_allow, which is -- +-- conditioned with a valid write. -- +-- -- +-- Note: To have utilized the full address space (512) -- +-- would have required extra logic to determine Full/Empty -- +-- on equal addresses, and this would have slowed down the -- +-- overall performance, which was the top priority. -- +-- -- +---------------------------------------------------------------- + +ecomp(0) <= (NOT (write_addrgray(0) XOR read_addrgray(0)) AND empty) OR + (NOT (write_addrgray(0) XOR read_nextgray(0)) AND NOT empty); +ecomp(1) <= (NOT (write_addrgray(1) XOR read_addrgray(1)) AND empty) OR + (NOT (write_addrgray(1) XOR read_nextgray(1)) AND NOT empty); +ecomp(2) <= (NOT (write_addrgray(2) XOR read_addrgray(2)) AND empty) OR + (NOT (write_addrgray(2) XOR read_nextgray(2)) AND NOT empty); +ecomp(3) <= (NOT (write_addrgray(3) XOR read_addrgray(3)) AND empty) OR + (NOT (write_addrgray(3) XOR read_nextgray(3)) AND NOT empty); +ecomp(4) <= (NOT (write_addrgray(4) XOR read_addrgray(4)) AND empty) OR + (NOT (write_addrgray(4) XOR read_nextgray(4)) AND NOT empty); +ecomp(5) <= (NOT (write_addrgray(5) XOR read_addrgray(5)) AND empty) OR + (NOT (write_addrgray(5) XOR read_nextgray(5)) AND NOT empty); +ecomp(6) <= (NOT (write_addrgray(6) XOR read_addrgray(6)) AND empty) OR + (NOT (write_addrgray(6) XOR read_nextgray(6)) AND NOT empty); +ecomp(7) <= (NOT (write_addrgray(7) XOR read_addrgray(7)) AND empty) OR + (NOT (write_addrgray(7) XOR read_nextgray(7)) AND NOT empty); +ecomp(8) <= (NOT (write_addrgray(8) XOR read_addrgray(8)) AND empty) OR + (NOT (write_addrgray(8) XOR read_nextgray(8)) AND NOT empty); + +emuxcy0: MUXCY_L port map (DI=>gnd,CI=>pwr, S=>ecomp(0),LO=>emuxcyo(0)); +emuxcy1: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(0),S=>ecomp(1),LO=>emuxcyo(1)); +emuxcy2: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(1),S=>ecomp(2),LO=>emuxcyo(2)); +emuxcy3: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(2),S=>ecomp(3),LO=>emuxcyo(3)); +emuxcy4: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(3),S=>ecomp(4),LO=>emuxcyo(4)); +emuxcy5: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(4),S=>ecomp(5),LO=>emuxcyo(5)); +emuxcy6: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(5),S=>ecomp(6),LO=>emuxcyo(6)); +emuxcy7: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(6),S=>ecomp(7),LO=>emuxcyo(7)); +emuxcy8: MUXCY_L port map (DI=>gnd,CI=>emuxcyo(7),S=>ecomp(8),LO=>emptyg); + +fcomp(0) <= (NOT (read_lastgray(0) XOR write_addrgray(0)) AND full) OR + (NOT (read_lastgray(0) XOR write_nextgray(0)) AND NOT full); +fcomp(1) <= (NOT (read_lastgray(1) XOR write_addrgray(1)) AND full) OR + (NOT (read_lastgray(1) XOR write_nextgray(1)) AND NOT full); +fcomp(2) <= (NOT (read_lastgray(2) XOR write_addrgray(2)) AND full) OR + (NOT (read_lastgray(2) XOR write_nextgray(2)) AND NOT full); +fcomp(3) <= (NOT (read_lastgray(3) XOR write_addrgray(3)) AND full) OR + (NOT (read_lastgray(3) XOR write_nextgray(3)) AND NOT full); +fcomp(4) <= (NOT (read_lastgray(4) XOR write_addrgray(4)) AND full) OR + (NOT (read_lastgray(4) XOR write_nextgray(4)) AND NOT full); +fcomp(5) <= (NOT (read_lastgray(5) XOR write_addrgray(5)) AND full) OR + (NOT (read_lastgray(5) XOR write_nextgray(5)) AND NOT full); +fcomp(6) <= (NOT (read_lastgray(6) XOR write_addrgray(6)) AND full) OR + (NOT (read_lastgray(6) XOR write_nextgray(6)) AND NOT full); +fcomp(7) <= (NOT (read_lastgray(7) XOR write_addrgray(7)) AND full) OR + (NOT (read_lastgray(7) XOR write_nextgray(7)) AND NOT full); +fcomp(8) <= (NOT (read_lastgray(8) XOR write_addrgray(8)) AND full) OR + (NOT (read_lastgray(8) XOR write_nextgray(8)) AND NOT full); + +fmuxcy0: MUXCY_L port map (DI=>gnd,CI=>pwr, S=>fcomp(0),LO=>fmuxcyo(0)); +fmuxcy1: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(0),S=>fcomp(1),LO=>fmuxcyo(1)); +fmuxcy2: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(1),S=>fcomp(2),LO=>fmuxcyo(2)); +fmuxcy3: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(2),S=>fcomp(3),LO=>fmuxcyo(3)); +fmuxcy4: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(3),S=>fcomp(4),LO=>fmuxcyo(4)); +fmuxcy5: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(4),S=>fcomp(5),LO=>fmuxcyo(5)); +fmuxcy6: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(5),S=>fcomp(6),LO=>fmuxcyo(6)); +fmuxcy7: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(6),S=>fcomp(7),LO=>fmuxcyo(7)); +fmuxcy8: MUXCY_L port map (DI=>gnd,CI=>fmuxcyo(7),S=>fcomp(8),LO=>fullg); + +end architecture trb_net_fifo_16bit_bram_dualport_arch; + -- 2.43.0