URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
[/] [open8_urisc/] [trunk/] [VHDL/] [o8_serlcd_tx.vhd] - Rev 333
Go to most recent revision | Compare with Previous | Blame | View Log
-- Copyright (c)2013, 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_serlcd_tx -- Description: Provides a client for sending data to a SPI attached LCD -- -- Register Map -- Address Function -- Offset Bitfield Description Read/Write -- 0x0 AAAAAAAA LCD Register Write (Read-Write*) -- 0x1 AAAAAAAA LCD Data Write (Read-Write*) -- 0x2 AAAAAAAA LCD Rearm Init Timer (Read-Write*) -- 0x3 AAAAAAAA LCD Backlight (Read-Write) -- -- Note: Reading any offset will report the interface status -- CBA C: TX Ready Status (interface is IDLE) -- B: SPI SDO status (raw reading of SPI SDO line) -- A: IO Timeout > 0 (Set if IO timer expired) -- -- Revision History -- Author Date Change ------------------ -------- --------------------------------------------------- -- Seth Henry 04/16/20 Revision block added -- Seth Henry 05/18/20 Added write qualification input 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.open8_pkg.all; entity o8_serlcd_tx is generic( Address : ADDRESS_TYPE ); port( Open8_Bus : in OPEN8_BUS_TYPE; Write_Qual : in std_logic := '1'; Rd_Data : out DATA_TYPE; Interrupt : out std_logic; -- SPI_CLK : out std_logic; SPI_SDI : out std_logic; SPI_SDO : in std_logic ); end entity; architecture behave of o8_serlcd_tx is alias Clock is Open8_Bus.Clock; alias Reset is Open8_Bus.Reset; constant User_Addr : std_logic_vector(15 downto 2) := Address(15 downto 2); alias Comp_Addr is Open8_Bus.Address(15 downto 2); signal Addr_Match : std_logic; alias Reg_Sel_d is Open8_Bus.Address(1 downto 0); signal Reg_Sel_q : std_logic_vector(1 downto 0) := "00"; signal Wr_En_d : std_logic := '0'; signal Wr_En_q : std_logic := '0'; alias Wr_Data_d is Open8_Bus.Wr_Data; signal Wr_Data_q : DATA_TYPE := x"00"; signal Rd_En_d : std_logic := '0'; signal Rd_En_q : std_logic := '0'; signal Reg_Addr : std_logic_vector(1 downto 0) := (others => '0'); signal Reg_Data : std_logic_vector(7 downto 0) := (others => '0'); signal Reg_Valid : std_logic := '0'; signal Tx_Ready : std_logic := '0'; -- Data Format -- <A1><A0><D7><D6><D5><D4><D3><D2><D1><D0> type IO_STATES is ( INIT, IDLE, SETUP, RISING, HOLD, FALLING, IF_WAIT ); signal io_state : IO_STATES; signal tx_buffer : std_logic_vector(10 downto 0); alias ADDR is tx_buffer(10 downto 9); alias DATA is tx_buffer(8 downto 1); alias RUNOUT is tx_buffer(0); signal bit_cnt : std_logic_vector(3 downto 0) := (others => '0'); constant VEC_LEN : integer := tx_buffer'length - 1; constant BITS : std_logic_vector(3 downto 0) := conv_std_logic_vector(VEC_LEN,4); signal snh_tmr : std_logic_vector(2 downto 0) := (others => '0'); signal SPI_SDO_q : std_logic_vector(2 downto 0) := "000"; signal TX_Clk : std_logic := '0'; signal TX_Out : std_logic := '0'; begin Addr_Match <= '1' when Comp_Addr = User_Addr else '0'; Wr_En_d <= Addr_Match and Open8_Bus.Wr_En and Write_Qual; Rd_En_d <= Addr_Match and Open8_Bus.Rd_En; SPI_CLK <= TX_Clk; SPI_SDI <= TX_Out; io_reg: process( Clock, Reset ) begin if( Reset = Reset_Level )then Reg_Sel_q <= "00"; Wr_En_q <= '0'; Wr_Data_q <= x"00"; Rd_En_q <= '0'; Rd_Data <= OPEN8_NULLBUS; Reg_Addr <= (others => '0'); Reg_Data <= x"00"; Reg_Valid <= '0'; elsif( rising_edge( Clock ) )then Reg_Sel_q <= Reg_Sel_d; Wr_En_q <= Wr_En_d; Wr_Data_q <= Wr_Data_d; Reg_Valid <= '0'; if( Wr_En_q = '1' )then Reg_Addr <= Reg_Sel_q; Reg_Data <= Wr_Data_q; Reg_Valid <= '1'; end if; Rd_En_q <= Rd_En_d; Rd_Data <= OPEN8_NULLBUS; if( Rd_En_q = '1' )then Rd_Data(7) <= Tx_Ready; end if; end if; end process; tx_proc: process( Clock, Reset ) begin if( Reset = Reset_Level )then io_state <= INIT; tx_buffer <= (others => '0'); bit_cnt <= (others => '0'); snh_tmr <= (others => '0'); TX_Clk <= '0'; TX_Out <= '0'; Tx_Ready <= '0'; Interrupt <= '0'; SPI_SDO_q <= (others => '1'); elsif( rising_edge(Clock) )then TX_Clk <= '1'; TX_Out <= tx_buffer(conv_integer(bit_cnt)); SPI_SDO_q <= SPI_SDO_q(1 downto 0) & to_X01(SPI_SDO); Tx_Ready <= '0'; Interrupt <= '0'; case( io_state )is when INIT => if( or_reduce(SPI_SDO_q) = '0' )then io_state <= IDLE; end if; when IDLE => Tx_Ready <= '1'; bit_cnt <= (others => '0'); snh_tmr <= (others => '1'); if( Reg_Valid = '1' )then ADDR <= Reg_Addr; DATA <= Reg_Data; bit_cnt <= BITS; io_state <= FALLING; end if; when SETUP => TX_Clk <= '0'; snh_tmr <= snh_tmr - 1; if( snh_tmr = 0 )then io_state <= RISING; end if; when RISING => snh_tmr <= (others => '1'); io_state <= HOLD; when HOLD => snh_tmr <= snh_tmr - 1; if( snh_tmr = 0 )then bit_cnt <= bit_cnt - or_reduce(bit_cnt); io_state <= FALLING; end if; when FALLING => TX_Clk <= '0'; snh_tmr <= (others => '1'); io_state <= SETUP; if( bit_cnt = 0 )then TX_Clk <= '1'; io_state <= IF_WAIT; end if; when IF_WAIT => if( or_reduce(SPI_SDO_q) = '0' )then Interrupt <= '1'; io_state <= IDLE; end if; when others => null; end case; end if; end process; end architecture;
Go to most recent revision | Compare with Previous | Blame | View Log