URL
https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk
Subversion Repositories open8_urisc
[/] [open8_urisc/] [trunk/] [VHDL/] [o8_7seg.vhd] - Rev 307
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_7seg -- Description: Drives up to two 7-segment displays in either common cathode -- : or common anode mode with per-display PWM brightness. -- -- Register Map: -- Offset Bitfield Description Read/Write -- 0x00 ---AAAAA Display 1 value (RW) -- 0x01 ---AAAAA Display 2 value (RW) -- 0x02 AAAAAAAA Display 1 brightness (RW) -- 0x03 AAAAAAAA Display 2 brightness (RW) -- -- Revision History -- Author Date Change ------------------ -------- --------------------------------------------------- -- Seth Henry 05/08/19 Design Start -- 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_7seg is generic( Default_LED1_Value : std_logic_vector(4 downto 0); Default_LED1_Bright : DATA_TYPE := x"FF"; Default_LED2_Value : std_logic_vector(4 downto 0); Default_LED2_Bright : DATA_TYPE := x"FF"; Common_Cathode : boolean := TRUE; Address : ADDRESS_TYPE ); port( Open8_Bus : in OPEN8_BUS_TYPE; Write_Qual : in std_logic := '1'; Rd_Data : out DATA_TYPE; -- SegLED1 : out std_logic_vector(6 downto 0); SegLED2 : out std_logic_vector(6 downto 0) ); end entity; architecture behave of o8_7seg 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 LED1_Reg : std_logic_vector(4 downto 0); signal LED1_Brt : DATA_TYPE; signal LED2_Reg : std_logic_vector(4 downto 0); signal LED2_Brt : DATA_TYPE; signal LED1_PDM : std_logic; signal LED1_Ext : std_logic_vector(6 downto 0); signal LED2_PDM : std_logic; signal LED2_Ext : std_logic_vector(6 downto 0); signal SegLED1_Full : std_logic_vector(6 downto 0); signal SegLED2_Full : std_logic_vector(6 downto 0); -- Standard 7-Segment Numeric Display -- -- -A- -- | | -- F B -- | | -- -G- -- | | -- E C -- | | -- -D- (DP) type LED_DEFS_TYPE is array(0 to 31) of std_logic_vector(6 downto 0); constant CHAR_DEFINITIONS : LED_DEFS_TYPE := ( -- GFEDCBA "0111111", -- 00 -> 0 "0000110", -- 01 -> 1 "1011011", -- 02 -> 2 "1001111", -- 03 -> 3 "1100110", -- 04 -> 4 "1101101", -- 05 -> 5 "1111101", -- 06 -> 6 "0000111", -- 07 -> 7 "1111111", -- 08 -> 8 "1101111", -- 09 -> 9 "1110111", -- 10 -> A "1111100", -- 11 -> B "1011000", -- 12 -> C "1011110", -- 13 -> D "1111001", -- 14 -> E "1110001", -- 15 -> F "0111101", -- 16 -> G "1110110", -- 17 -> H "0000100", -- 18 -> i "0001110", -- 19 -> J "0111000", -- 20 -> L "1010100", -- 21 -> n "1011100", -- 22 -> o "1110011", -- 23 -> P "1010000", -- 24 -> r "0011100", -- 25 -> u "1101110", -- 26 -> y "1000000", -- 27 -> - "1001000", -- 28 -> = "1100011", -- 29 -> DEG "0000010", -- 30 -> ' "0000000" -- 31 -> " " ); 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; 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; LED1_Reg <= Default_LED1_Value; LED2_Reg <= Default_LED2_Value; LED1_Brt <= Default_LED1_Bright; LED2_Brt <= Default_LED2_Bright; elsif( rising_edge( Clock ) )then Reg_Sel_q <= Reg_Sel_d; Wr_En_q <= Wr_En_d; Wr_Data_q <= Wr_Data_d; if( Wr_En_q = '1' )then case( Reg_Sel_q )is when "00" => LED1_Reg <= Wr_Data_q(4 downto 0); when "01" => LED2_Reg <= Wr_Data_q(4 downto 0); when "10" => LED1_Brt <= Wr_Data_q; when "11" => LED2_Brt <= Wr_Data_q; when others => null; end case; end if; Rd_En_q <= Rd_En_d; Rd_Data <= OPEN8_NULLBUS; if( Rd_En_q = '1' )then case( Reg_Sel_q )is when "00" => Rd_Data <= "000" & LED1_Reg; when "01" => Rd_Data <= "000" & LED2_Reg; when "10" => Rd_Data <= LED1_Brt; when "11" => Rd_Data <= LED2_Brt; when others => null; end case; end if; end if; end process; U_LED1_PWM : entity work.vdsm8 generic map( Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, DACin => LED1_Brt, DACout => LED1_PDM ); U_LED2_PWM : entity work.vdsm8 generic map( Reset_Level => Reset_Level ) port map( Clock => Clock, Reset => Reset, DACin => LED2_Brt, DACout => LED2_PDM ); LED1_Ext <= (others => LED1_PDM); LED2_Ext <= (others => LED2_PDM); SegLED1_Full <= CHAR_DEFINITIONS(conv_integer(LED1_Reg)); SegLED2_Full <= CHAR_DEFINITIONS(conv_integer(LED2_Reg)); Common_Cathode_Mode : if( Common_Cathode )generate LUT_proc: process( Clock, Reset ) begin if( Reset = Reset_Level )then SegLED1 <= (others => '0'); SegLED2 <= (others => '0'); elsif( rising_edge(Clock) )then SegLED1 <= (SegLED1_Full and LED1_Ext) xor "1111111"; SegLED2 <= (SegLED2_Full and LED2_Ext) xor "1111111"; end if; end process; end generate; Common_Anode_Mode : if( not Common_Cathode )generate LUT_proc: process( Clock, Reset ) begin if( Reset = Reset_Level )then SegLED1 <= (others => '1'); SegLED2 <= (others => '1'); elsif( rising_edge(Clock) )then SegLED1 <= (SegLED1_Full and LED1_Ext); SegLED2 <= (SegLED2_Full and LED2_Ext); end if; end process; end generate; end architecture;
Go to most recent revision | Compare with Previous | Blame | View Log