--============================================================================== -- -- Function : ODIN duplex card -- VHDL code derived from 16bit version of -- G-LINK-S-LINK LDC - kelby anderson LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- Maxplus needs this, -- comment out for leapfrog library lpm; use lpm.lpm_components.all; --============================================================================== ENTITY LDC IS --============================================================================= port( -------------------------------------------------------------------------------- -- INPUTS -------------------------------------------------------------------------------- QCLK : in std_logic; -- 40 Mhz from Quartz HP_STRBOUT : in std_logic; -- RX clock from HP RXA_READY : in std_logic; -- Low when link is active RXA_DATA : in std_logic; -- G control word RXA_CNTL : in std_logic; -- G data word RXA_ERROR : in std_logic; -- Error flag RXA_FLAG : in std_logic; RXB_READY : in std_logic; -- Low when link is active RXB_DATA : in std_logic; -- G control word RXB_CNTL : in std_logic; -- G data word RXB_ERROR : in std_logic; -- Error flag RXB_FLAG : in std_logic; HP_DA : in std_logic_vector(15 downto 0); HP_DB : in std_logic_vector(15 downto 0); UDW : in std_logic_vector(1 downto 0); RXB_DSLIP : in std_logic; URL : in std_logic_vector(3 downto 0); URESET_N : in std_logic; UXOFF_N : in std_logic; UTDO_N : in std_logic; -------------------------------------------------------------------------------- -- OUTPUTS -------------------------------------------------------------------------------- HP_FLAGSEL : out std_logic; -- Flag Mode Select HP_DIV : out std_logic_vector(1 downto 0); -- Baud rate RX_ESMPXENB : OUT std_logic; RX_RESET_N : OUT std_logic; RX_WSYNCDSB : OUT std_logic; LD : out std_logic_vector(31 downto 0); LCLK : out std_logic; -- S-Link Signals LCTRL_N : out std_logic; LWEN_N : out std_logic; LDOWN_N : out std_logic; LDERR_N : out std_logic; CK40TTL : out std_logic; TESTLED_N : out std_logic; -- Leds, lights when 0 DERRLED_N : out std_logic; LUPLED_N : out std_logic; FLOWCTLED_N : out std_logic; -- Unused Pins are connected to ground to improve gnd-bounce G : out std_logic_vector(29 downto 0); lclk2 : in std_logic; loop1 : in std_logic; loop2 : out std_logic; loop3 : in std_logic; loop4 : out std_logic; junk : out std_logic); end LDC; --============================================================================== ARCHITECTURE behavioural OF LDC IS --============================================================================== component CRCRX port ( CLK : in std_logic; HW_UP : in std_logic; RX_D : in std_logic_vector (15 downto 0); RX_D_O : out std_logic_vector (15 downto 0); RX_DATA : in std_logic; RX_DATA_O: out std_logic; RX_CNTL : in std_logic; RX_CNTL_O: out std_logic; RX_FLAG : in std_logic; RX_FLAG_O: out std_logic; RX_ERR : in std_logic; ERROR : out std_logic); end component; TYPE init_state is (DOWN, UP, RES1, RES2, RES3, LERR); TYPE reset_state is (OK, RSTNOW, WAITST); -- attribute TYPE_ENCODING_STYLE of init_state:type is ONEHOT; -- Note: the Altera settings such as coding style are in the file ldc.acf signal curr_reset, next_reset: reset_state; -- Reset SM signal curr_init, next_init : init_state; -- Link init SM signal inreg : std_logic_vector(15 downto 0); -- Input reg.(.q) signal inreg1 : std_logic_vector(15 downto 0); -- Input reg.(.q) signal cnt : std_logic_vector(3 downto 0); signal filt : std_logic_vector(10 downto 0); -- Filter signal ld_ad, LDr : std_logic_vector(31 downto 0); signal crc_word : std_logic_vector(31 downto 0); signal pipeline, pipe3 : std_logic_vector(31 downto 0); signal errled_n, linkrdy_n : std_logic; signal RXX_CNTL_O, RXX_DATA_O, inerr, LWENr_N, lup: std_logic; signal RXX_FLAG_O, sys_res, hp_up : std_logic; signal testpattern, tdata : std_logic_vector(32 downto 0); signal tloadena, tshiften, tshiftin, utestreg : std_logic; signal err, err2, err3_n, perr, perrh, perrl, t_error, elatch, testbit: std_logic; signal longwmode, wen2_n, ctl2_n, wen3_n, ctl3_n, tout_n: std_logic; signal wen4_n, wen5_n, ctrl4_n, ctl5_n: std_logic; signal slink_ctl, slink_dat, slink_cmd, slink_ctl_last : std_logic; signal slink_ctl2,slink_dat2,slink_cmd2,slink_cmd3 : std_logic; signal crc_rst2, crc_cmd2, crc_cmd3, crc_cmd4 : std_logic; signal crc_rst,crc_cal,crc_clk,crc_cmp : std_logic; signal clk2,clk2b, flag_en,CLK,CLK_N: std_logic; signal lup1, lup2 :std_logic; -- signal flag_count : std_logic_vector (0 downto 0); signal flag_count,next_count :std_logic; signal HP_D: std_logic_vector(15 downto 0); signal HP_LOOPEN : STD_LOGIC; signal TP3: std_logic; signal HP_SMRST1_N : std_logic; -- State m. reset signal HP_SMRST0_N : std_logic; -- State m. reset SIGNAL HP_ERROR,RXX_DATA,RXX_CNTL,RXX_READY,HP_FLAG : STD_LOGIC; begin -------------------------------------------------------------------------------- -- Non-registered OUTPUTS ------------------------------------------------------ TP3 <= '0'; junk <= tout_n and lclk2 AND UDW(0) AND UDW(1) AND RXB_DSLIP and URL(1) and URL(2) and URL(3) and URL(0); loop2 <= loop1; loop4 <= loop3; process (url) begin if(URL(0) = '1') then HP_D(15 downto 0) <= HP_DB(15 downto 0); HP_ERROR <= RXB_ERROR; HP_FLAG <= RXB_FLAG; RXX_DATA <= RXB_DATA; RXX_CNTL <= RXB_CNTL; RXX_READY <= RXB_READY; else HP_D(15 downto 0) <= HP_DA(15 downto 0); HP_ERROR <= RXA_ERROR; HP_FLAG <= RXA_FLAG; RXX_DATA <= RXA_DATA; RXX_CNTL <= RXA_CNTL; RXX_READY <= RXA_READY; end if; end process; RX_ESMPXENB <= '1'; -- kja RX_RESET_N <= HP_SMRST1_N; RX_WSYNCDSB <= '0'; HP_FLAGSEL <= '1'; HP_LOOPEN <= '1'; -- S.M 3 if TP3='0' (on) HP_DIV <= "01"; -- 350-900 MBaud/sec LCLK <= HP_STRBOUT; -- LCLK isInverted for better Tsu/Th CLK_N <= HP_STRBOUT; CLK <= not HP_STRBOUT; -- "Besides placing switching pins next to a ground pin, you can create a -- programmable ground by creating an output pin in your design that drives -- only ground. By connecting this output pin to ground on the board, the -- device ground will have another connection to the board ground, which helps -- reduce ground bounce."(page 532 in 1998 ALTERA data book) G <= (others => '0'); -- gnd outputs against gnd-bounce -------------------------------------------------------------------------------- -- EDGE SENSITIVE RESET: Generates a pulse on negative URESET_N edge ----------- reset_reg :process(CLK) begin if (CLK'event and CLK ='1') then curr_reset <= next_reset; end if; end process reset_reg; reset_machine :process(curr_reset, URESET_N) begin case curr_reset is when OK => -- No reset, URESET_N is high if (URESET_N ='0') then next_reset <= RSTNOW; else next_reset <= OK; end if; when RSTNOW => -- Reset pulse next_reset <= WAITST; when WAITST => -- Wait while URESET_N is low; if (URESET_N ='1') then next_reset <= OK; else next_reset <= WAITST; end if; when others => next_reset <= WAITST; end case; end process reset_machine; reset_out: process (curr_reset) begin case curr_reset is when RSTNOW => sys_res <= '1'; -- Active high system reset when others => sys_res <= '0'; end case; end process reset_out; -------------------------------------------------------------------------------- -- "Filtered" HPREADY (hpdown signal) ------------------------------------------ -- This signal has cca. 100ns wide negative pulses during -- synchronisation. Sync. with methode "3" @40mhz takes cca. 25ms -- hp_up goes down if RXX_READY goes down (G-Link Down) -- hp_up goes up if RXX_READY is high for >25us filter:process(CLK) begin if (CLK'event and CLK='1') then if (RXX_READY = '0') then filt <= (others => '0'); elsif (filt(10)='1') then filt <= filt; -- stop counting if MSB=1 else filt <= filt + '1'; -- filt(3) for sim. end if; end if; end process filter; hp_up <= filt(10); -- change to filt(3) for simulation! -------------------------------------------------------------------------------- -- LINK INIT STATE MACHINE ----------------------------------------------------- init_reg :process(CLK) begin if (CLK'event and CLK='1') then curr_init <= next_init; end if; end process init_reg; init_machine: process (curr_init, sys_res) begin case curr_init is when DOWN => -- Wait for LINKRDY; Power-On state if (hp_up = '1') then next_init <= UP; -- Link UP if LINKRDY elsif (sys_res = '1') then next_init <= RES1; -- HP reset possible in DOWN state else next_init <= DOWN; end if; when UP => -- when LINK UP if (sys_res = '1') then next_init <= RES1; elsif (hp_up = '0') then next_init <= LERR; else next_init <= UP; end if; when RES1 => -- HP Reset Pulse Here! next_init <= RES2; -- As in S-LINK spec, when RES2 => -- LDOWN Period for 4 LCLK if (hp_up = '0') then next_init <= RES3; -- Wait for HP-Down else NEXT_INIT <= RES2; end if; when RES3 => next_init <= DOWN; when LERR => -- Link error, quit with URESET# case sys_res is -- According to S-LINK spec. when '1' => next_init <= RES1; -- Reset HP when others => next_init <= LERR; end case; when others => -- Same as LERR (Link Error) case sys_res is when '1' => next_init <= RES1; when others => next_init <= LERR; end case; end case; end process init_machine; init_out: process (CLK) begin if (CLK'event and CLK='1') then case curr_init is when UP => LDOWN_N <= not utestreg; -- Link is active in UP state LUPLED_N <= utestreg; -- But DOWN in selftest mode HP_SMRST1_N <= '1'; lup <= '1'; when RES1 => LDOWN_N <= '0'; -- LDOWN is '0' in Test Mode LUPLED_N <= '1'; HP_SMRST1_N <= '0'; -- Reset HP Here! lup <= '0'; when others => LDOWN_N <= '0'; LUPLED_N <= '1'; HP_SMRST1_N <= '1'; lup <= '0'; end case; end if; end process init_out; HP_SMRST0_N <= '1'; -- Not used, reset only with -- HP_SMRST1_N refclock: process (curr_init) begin case TP3 is when '1' => CK40TTL <= '0'; -- TP3 off, Lock Methode "2" when others => -- TP3 on, Lock Methode "3" case curr_init is when UP => CK40TTL <= '0'; -- Disabled when UP for less PCB noise when others => CK40TTL <= QCLK; -- Send Reference Clock for G-Link end case; end case; end process refclock; -------------------------------------------------------------------------------- -- DATA ERROR and FLOWCTRL LEDS ------------------------------------------------ e_led: process (CLK) begin if (CLK'event and CLK='1') then if (curr_init /= UP) then errled_n <= '1'; -- Goes off on URESET# or LDOWN# elsif (err ='1') then errled_n <= '0'; -- Illuminates on error signal else errled_n <= errled_n; end if; end if; end process e_led; DERRLED_N <= errled_n; -- f_led: process (CLK) begin -- if (CLK'event and CLK='1') then -- if (UXOFF_N = '0') then FLOWCTLED_N <= '0'; -- Goes on on UXOFF_N# -- else FLOWCTLED_N <= '1'; -- end if; -- end if; -- end process f_led; f_led: process(HP_ERROR) begin if (flag_en = '1') then FLOWCTLED_N <= '1'; elsif(HP_ERROR = '1') then FLOWCTLED_N <= '0'; end if; end process f_led; ---------------------------------------------------------------------------- -----INPUT REGISTER (1. pipeline stage)------------------------------------- crcrxcal : CRCRX port map ( CLK => CLK, HW_UP => lup, RX_D => HP_D(15 downto 0), RX_D_O => inreg1, RX_DATA => RXX_DATA, RX_DATA_O => RXX_DATA_O, RX_CNTL => RXX_CNTL, RX_CNTL_O => RXX_CNTL_O, RX_FLAG => HP_FLAG, RX_FLAG_O => RXX_FLAG_O, RX_ERR => HP_ERROR, ERROR => t_error); inputreg: process (CLK_N,CLK) begin if (CLK'event and CLK='1') then inerr <= HP_ERROR; inreg <= inreg1; --slink_ctl <= (not RXX_DATA_O) and RXX_CNTL_O; slink_ctl <= '0'; slink_dat <= RXX_DATA_O and (not RXX_CNTL_O) and RXX_FLAG_O; --slink_cmd <= RXX_DATA_O and RXX_CNTL_O; slink_cmd <= '0'; end if; if (CLK_N'event and CLK_N='1') then slink_cmd2 <= slink_cmd; end if; end process inputreg; --- -- Some Clocks --- delayclk: process (CLK,CLK_N) begin if (CLK_N'event and CLK_N = '1') then clk2 <= clk2b; lup2 <= lup1; flag_en <= (not HP_D(15)) and (not HP_D(14)) and (not HP_D(13)) and HP_D(12) and (not HP_D(11)) and (not HP_D(10)) and (not HP_D(9)) and HP_D(8) and (not HP_D(7)) and (not HP_D(6)) and (not HP_D(5)) and HP_D(4) and (not HP_D(3)) and (not HP_D(2)) and (not HP_D(1)) and HP_D(0) and RXX_DATA and (not HP_FLAG); end if; if (CLK'event and CLK = '1') then lup1 <= lup; end if; end process delayclk; clk2b <= not clk2; flag_counter: process(CLK,CLK_N) begin if(flag_en = '1') then flag_count <= '0'; elsif(CLK'event and CLK = '1') then flag_count <= not next_count; end if; if(CLK_N'event and CLK_N = '1') then next_count <= flag_count; end if; end process; -- flag_counter: lpm_counter generic map (LPM_WIDTH =>1) -- port map (clock => CLK, -- aclr => flag_en, -- q => flag_count); ---------------------------------------------------------------------------- -----CRC CHECK (1. pipeline stage)------------------------------------------ ----------------------------------------------------------------------------- -----32 BIT MODE DEMUX (2. pipeline stage) ---------------------------------- dmx: process (CLK_N) begin if (CLK_N'event and CLK_N = '1') then -- if ( slink_cmd2 = '1' ) then -- wen2_n <='1'; -- ctl2_n <='1'; -- slink_dat2 <= '0'; -- slink_ctl2 <= '0'; -- elsif ( slink_ctl = '1') then -- if (flag_count(0) = '0') then -- if (flag_count = '0') then -- pipeline(31 downto 16) <= inreg(15 downto 0); -- high halfword -- wen2_n <= '1'; -- do not write -- ctl2_n <= '1'; -- slink_ctl2 <= '0'; -- slink_dat2 <= '0'; -- -- elsif (flag_count(0) = '1') then -- elsif (flag_count = '1') then -- pipeline(15 downto 0) <= inreg(15 downto 0); -- lower halfword -- wen2_n <= '0'; -- write -- ctl2_n <= not(slink_ctl); -- slink_ctl2 <= slink_ctl; -- slink_dat2 <= slink_dat; -- end if; -- els if ( slink_dat = '1') then -- if (flag_count(0) = '0') then if (flag_count = '0') then pipeline(31 downto 16) <= inreg(15 downto 0); -- high halfword wen2_n <= '1'; -- do not write ctl2_n <= '1'; slink_ctl2 <= '0'; slink_dat2 <= '0'; -- elsif (flag_count(0) = '1') then elsif (flag_count = '1') then pipeline(15 downto 0) <= inreg(15 downto 0); -- lower halfword wen2_n <= '0'; -- write ctl2_n <= not(slink_ctl); slink_ctl2 <= slink_ctl; slink_dat2 <= slink_dat; end if; else wen2_n <= '1'; ctl2_n <= '1'; slink_dat2 <= '0'; slink_ctl2 <= '0'; end if; err2 <= inerr; end if; end process dmx; -------------------------------------------------------------------------------- -----3. PIPELINE --------------------------------------------------------------- pipe: process (CLK) begin if (CLK'event and CLK='1') then if (slink_dat2 = '1') then pipe3(31 downto 0) <= pipeline(31 downto 0); -- data word elsif (slink_ctl2 = '1') then pipe3(31 downto 4) <= pipeline(31 downto 4); pipe3(3) <= '0'; -- Reserved bit pipe3(2) <= '0'; -- Reserved bit pipe3(1) <= '0'; -- Used to be parity error pipe3(0) <= elatch; -- Error in previous data block end if; err <= inerr; -- this illuminates the Error LED wen3_n <= wen2_n or (not lup2); ctl3_n <= ctl2_n; end if; end process pipe; -------------------------------------------------------------------------------- -----TEST MODE LATCH ----------------------------------------------------------- testbit <= utestreg; utestreg <= '0'; -- no test mode end if TESTLED_N <= not utestreg; -------------------------------------------------------------------------------- -----UTDO# LATCH --------------------------------------------------------------- utdo: process (CLK,UTDO_N) begin if (CLK'event and CLK='1') then case curr_init is when UP => tout_n <= tout_n; -- Keep value when others => tout_n <= UTDO_N; -- Update on reset end case; end if; end process utdo; -- ERROR LATCH ----------------------------------------------------------------- errlatch: process (CLK) begin if (CLK'event and CLK='1') then if ((curr_init /= UP) or (ctl3_n = '0')) then -- Disable during initialisation elatch <= '0'; -- Clear on Ctrl Word elsif ( t_error = '1') then -- Error in data word elatch <= '1'; else elatch <= elatch; -- Keep value end if; end if; end process errlatch; -------------------------------------------------------------------------------- -- OUTPUT REGISTER ------------------------------------------------------------- outputreg: process (CLK_N) begin if (CLK_N'event and CLK_N='1') then LD <= pipe3; LDERR_N <= not(elatch); LCTRL_N <= ctl3_n; LWEN_N <= wen3_n; end if; end process outputreg; -------------------------------------------------------------------------------- -----TEST DATA CHECKER --------------------------------------------------------- --crc_32 : crc_maker port map ( data => pipe3, -- crc => crc_word, -- crc_rst => crc_rst2, -- crc_cal => crc_cal, -- crc_clk => clk2b ); --crc_comp: lpm_compare generic map (LPM_WIDTH => 32) -- port map ( dataa => pipeline, -- datab => crc_word, -- aneb => crc_cmp); --crc_chk : process (CLK) begin --if (CLK'event and CLK='1') then -- if (slink_cmd ='0' and slink_cmd2 = '1') then -- --t_error <= crc_cmp; -- t_error <= '0'; -- else -- t_error <= '0'; -- end if; --end if; --end process crc_chk; end behavioural; --============================================================================== -- END OF FILE --==============================================================================