URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
[/] [open8_urisc/] [trunk/] [VHDL/] [o8_sdlc_if.vhd] - Rev 196
Go to most recent revision | Compare with Previous | Blame | View Log
-- Copyright (c)2020 Jeremy Seth Henry -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions are met: -- * Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- * Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution, -- where applicable (as part of a user interface, debugging port, etc.) -- -- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY -- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- -- VHDL Units : o8_sdlc_if -- Description: Provides a full memory-mapped SDLC stack with automatic CRC16 -- Checksum insertion and integrity checking. -- -- Transmit Memory Map -- "0_0000_0000" (0x000) TX Buffer START -- "0_1111_1101" (0x0FD) TX Buffer END -- "0_1111_1110" (0x0FE) Clock Status* -- "0_1111_1111" (0x0FF) TX Length / Status** -- -- Receive Memory Map -- "1_0000_0000" (0x100) RX Buffer START -- "1_1111_1101" (0x1FD) RX Buffer END -- "1_1111_1110" (0x0FE) Reserved -- "1_1111_1111" (0x1FF) RX Length / Status*** -- -- * Address 0xFE reports the SDLC bit clock status and updates on changes. -- 1) If BClk_Okay = '0' (Bitclock is NOT present), the field will report -- 0x00. Otherwise, it will report 0xFF if the bitclock is present. -- 2) Writing any value to the register will cause the controller to -- silently reset the clock status without causing an interrupt. -- -- ** This location serves as the control/status register for transmit -- 1) Writing a value between 1 and 253 will trigger the transmit engine, -- using the write value as the packet length. -- 2) Values 0x00, 0xFE, or 0xFF are invalid, and will be ignored. -- 3) This value will change from the user written value to 0xFF once the -- packet is transmitted to indicate the transmission is complete. -- -- *** This location serves as the status register for the receive -- 1) This value is only updated on reception of a full frame, indicated -- by a start followed by a stop flag. Incomplete frames are ignored. -- 2) If the packet CRC matches the transmitted CRC, the packet is -- considered valid, and the received length (less CRC) is written. -- 3) If the packet CRC doesn't match, a value of ERR_CHECKSUM is written. -- 4) If too many bytes are received (buffer overflow), a value of -- ERR_LENGTH is written. library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; library work; use work.open8_pkg.all; library work; use work.sdlc_serial_pkg.all; entity o8_sdlc_if is generic( Monitor_Enable : boolean := true; Attach_Monitor_to_CPU_Side : boolean := false; Poly_Init : std_logic_vector(15 downto 0) := x"0000"; Set_As_Master : boolean := true; Clock_Offset : integer := 6; BitClock_Freq : real := 500000.0; Sys_Freq : real := 100000000.0; Reset_Level : std_logic := '1'; Address : ADDRESS_TYPE ); port( Clock : in std_logic; Reset : in std_logic; -- Bus_Address : in ADDRESS_TYPE; Wr_Enable : in std_logic; Wr_Data : in DATA_TYPE; Rd_Enable : in std_logic; Rd_Data : out DATA_TYPE; Interrupt : out std_logic; -- Serial IO SDLC_In : in std_logic; SDLC_SClk : in std_logic; SDLC_MClk : out std_logic; SDLC_Out : out std_logic ); end entity; architecture behave of o8_sdlc_if is -- Connect the CPU to the dual-port memory constant Base_Addr : std_logic_vector(15 downto 9) := Address(15 downto 9); alias RAM_Upper_Addr is Bus_Address(15 downto 9); alias RAM_Lower_Addr is Bus_Address(8 downto 0); signal RAM_Addr_Match : std_logic := '0'; signal RAM_Wr_En : std_logic := '0'; signal RAM_Rd_En : std_logic := '0'; signal Rd_Data_i : DATA_TYPE := OPEN8_NULLBUS; constant Reg_Sub_Addr : std_logic_vector(8 downto 1) := x"7F"; alias Reg_Upper_Addr is Bus_Address(8 downto 1); alias Reg_Lower_Addr is Bus_Address(0); signal Reg_Addr : std_logic_vector(8 downto 1) := (others => '0'); signal Reg_Sel : std_logic := '0'; signal Reg_Wr_En : std_logic := '0'; signal Reg_Clk_Sel : std_logic := '0'; signal Reg_TxS_Sel : std_logic := '0'; -- Connect the serial engine to the dual-port memory signal DP_Addr : std_logic_vector(8 downto 0) := (others => '0'); signal DP_Wr_Data : DATA_IN_TYPE := x"00"; signal DP_Wr_En : std_logic := '0'; signal DP_Rd_Data : DATA_IN_TYPE := x"00"; signal BClk_RE : std_logic := '0'; signal BClk_FE : std_logic := '0'; signal TX_Wr_En : std_logic := '0'; signal TX_Wr_Flag : std_logic := '0'; signal TX_Wr_Data : DATA_IN_TYPE := x"00"; signal TX_Req_Next : std_logic := '0'; signal TX_CRC_Clr : std_logic := '0'; signal TX_CRC_En : std_logic := '0'; signal TX_CRC_Data : CRC_OUT_TYPE := x"0000"; alias TX_CRC_Data_LB is TX_CRC_Data(7 downto 0); alias TX_CRC_Data_UB is TX_CRC_Data(15 downto 8); signal TX_CRC_Valid : std_logic := '0'; signal RX_Valid : std_logic := '0'; signal RX_Flag : std_logic := '0'; signal RX_Data : DATA_IN_TYPE := x"00"; signal RX_Idle : std_logic := '0'; signal RX_CRC_Clr : std_logic := '0'; signal RX_CRC_En : std_logic := '0'; signal RX_CRC_Data : CRC_OUT_TYPE := x"0000"; signal RX_CRC_Valid : std_logic := '0'; signal BClk_Okay : std_logic := '0'; begin -- This decode needs to happen immediately, to give the RAM a chance to -- do the lookup before we have to set Rd_Data RAM_Addr_Match <= '1' when Base_Addr = RAM_Upper_Addr else '0'; RAM_Wr_En <= RAM_Addr_Match and Wr_Enable; CPU_RAM_proc: process( Reset, Clock ) begin if( Reset = Reset_Level )then Reg_Addr <= (others => '0'); Reg_Wr_En <= '0'; Reg_Clk_Sel <= '0'; Reg_TxS_Sel <= '0'; RAM_Rd_En <= '0'; Rd_Data <= OPEN8_NULLBUS; elsif( rising_edge(Clock) )then Reg_Addr <= Reg_Upper_Addr; Reg_Sel <= Reg_Lower_Addr; Reg_Wr_En <= RAM_Addr_Match and Wr_Enable; Reg_Clk_Sel <= '0'; Reg_TxS_Sel <= '0'; if( Reg_Addr = Reg_Sub_Addr )then Reg_Clk_Sel <= Reg_Wr_En and not Reg_Sel; Reg_TxS_Sel <= Reg_Wr_En and Reg_Sel; end if; RAM_Rd_En <= RAM_Addr_Match and Rd_Enable; Rd_Data <= OPEN8_NULLBUS; if( RAM_Rd_En = '1' )then Rd_Data <= Rd_Data_i; end if; end if; end process; U_RAM : entity work.ram_dp512b_core port map( clock => Clock, address_a => RAM_Lower_Addr, address_b => DP_Addr, data_a => Wr_Data, data_b => DP_Wr_Data, wren_a => RAM_Wr_En, wren_b => DP_Wr_En, q_a => Rd_Data_i, q_b => DP_Rd_Data ); Attach_to_CPU_side: if( Monitor_Enable and Attach_Monitor_to_CPU_Side )generate U_MON: entity work.monitor port map( clock => Clock, address => RAM_Lower_Addr, data => Wr_Data, wren => RAM_Wr_En, q => open ); end generate; Attach_to_Int_side: if( Monitor_Enable and not Attach_Monitor_to_CPU_Side )generate U_MON: entity work.monitor port map( clock => Clock, address => DP_Addr, data => DP_Wr_Data, wren => DP_Wr_En, q => open ); end generate; U_BCLK : entity work.sdlc_serial_clk generic map( Set_As_Master => Set_As_Master, BitClock_Freq => BitClock_Freq, Reset_Level => Reset_Level, Sys_Freq => Sys_Freq ) port map( Clock => Clock, Reset => Reset, -- BClk_In => SDLC_SClk, BClk_Out => SDLC_MClk, BClk_FE => BClk_FE, BClk_RE => BClk_RE, BClk_Okay => BClk_Okay ); U_CTRL : entity work.sdlc_serial_ctrl generic map( Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, -- BClk_Okay => BClk_Okay, -- Reg_Clk_Sel => Reg_Clk_Sel, Reg_TxS_Sel => Reg_TxS_Sel, -- DP_Addr => DP_Addr, DP_Wr_Data => DP_Wr_Data, DP_Wr_En => DP_Wr_En, DP_Rd_Data => DP_Rd_Data, -- TX_Wr_En => TX_Wr_En, TX_Wr_Flag => TX_Wr_Flag, TX_Wr_Data => TX_Wr_Data, TX_Req_Next => TX_Req_Next, -- TX_CRC_Clr => TX_CRC_Clr, TX_CRC_En => TX_CRC_En, TX_CRC_Data => TX_CRC_Data, TX_CRC_Valid => TX_CRC_Valid, -- RX_Valid => RX_Valid, RX_Flag => RX_Flag, RX_Data => RX_Data, RX_Idle => RX_Idle, -- RX_CRC_Clr => RX_CRC_Clr, RX_CRC_En => RX_CRC_En, RX_CRC_Data => RX_CRC_Data, RX_CRC_Valid => RX_CRC_Valid, -- Interrupt => Interrupt ); U_TX_SER : entity work.sdlc_serial_tx generic map( Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, -- BClk_FE => BClk_FE, BClk_RE => BClk_RE, BClk_Okay => BClk_Okay, -- TX_En => TX_Wr_En, TX_FSS_Flag => TX_Wr_Flag, TX_Data => TX_Wr_Data, TX_Req_Next => TX_Req_Next, -- Serial_Out => SDLC_Out ); U_TX_CRC : entity work.sdlc_crc16_ccitt generic map( Poly_Init => Poly_Init, Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, -- Clear => TX_CRC_Clr, Wr_Data => TX_Wr_Data, Wr_En => TX_CRC_En, -- CRC16_Out => TX_CRC_Data, CRC16_Valid => TX_CRC_Valid ); U_RX_SER : entity work.sdlc_serial_rx generic map( Set_As_Master => Set_As_Master, Clock_Offset => Clock_Offset, Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, -- BClk_RE => BClk_RE, BClk_Okay => BClk_Okay, -- Serial_In => SDLC_In, -- RX_Valid => RX_Valid, RX_Flag => RX_Flag, RX_Data => RX_Data, RX_Idle => RX_Idle ); U_RX_CRC : entity work.sdlc_crc16_ccitt generic map( Poly_Init => Poly_Init, Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, -- Clear => RX_CRC_Clr, Wr_Data => RX_Data, Wr_En => RX_CRC_En, -- CRC16_Out => RX_CRC_Data, CRC16_Valid => RX_CRC_Valid ); end architecture;
Go to most recent revision | Compare with Previous | Blame | View Log