URL
https://opencores.org/ocsvn/w11/w11/trunk
Subversion Repositories w11
[/] [w11/] [tags/] [w11a_V0.5/] [rtl/] [bplib/] [s3board/] [s3_dispdrv.vhd] - Rev 37
Go to most recent revision | Compare with Previous | Blame | View Log
-- $Id: s3_dispdrv.vhd 314 2010-07-09 17:38:41Z mueller $ -- -- Copyright 2007-2010 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de> -- -- This program is free software; you may redistribute and/or modify it under -- the terms of the GNU General Public License as published by the Free -- Software Foundation, either version 2, or at your option any later version. -- -- This program is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- for complete details. -- ------------------------------------------------------------------------------ -- Module Name: s3_dispdrv - syn -- Description: s3board: 7 segment display driver -- -- Dependencies: - -- Test bench: - -- Target Devices: generic -- Tool versions: xst 8.1, 8.2, 9.1, 9.2, 11.4; ghdl 0.18-0.26 -- Revision History: -- Date Rev Version Comment -- 2010-04-17 278 1.1.1 renamed from dispdrv -- 2010-03-29 272 1.1 add all ANO off time to allow to driver turn-off -- delay and to avoid cross talk between digits -- 2007-12-16 101 1.0.1 use _N for active low -- 2007-09-16 83 1.0 Initial version ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use work.slvtypes.all; entity s3_dispdrv is -- 7 segment display driver generic ( CDWIDTH : positive := 6); -- clk divider width (must be >= 5) port ( CLK : in slbit; -- clock DIN : in slv16; -- data DP : in slv4; -- decimal points ANO_N : out slv4; -- anodes (act.low) SEG_N : out slv8 -- segements (act.low) ); end s3_dispdrv; architecture syn of s3_dispdrv is type regs_type is record cdiv : std_logic_vector(CDWIDTH-1 downto 0); -- clock divider counter dcnt : slv2; -- digit counter end record regs_type; constant regs_init : regs_type := ( conv_std_logic_vector(0,CDWIDTH), (others=>'0') ); type hex2segtbl_type is array (0 to 15) of slv7; constant hex2segtbl : hex2segtbl_type := ("0111111", -- 0: "0000" "0000110", -- 1: "0001" "1011011", -- 2: "0010" "1001111", -- 3: "0011" "1100110", -- 4: "0100" "1101101", -- 5: "0101" "1111101", -- 6: "0110" "0000111", -- 7: "0111" "1111111", -- 8: "1000" "1101111", -- 9: "1001" "1110111", -- a: "1010" "1111100", -- b: "1011" "0111001", -- c: "1100" "1011110", -- d: "1101" "1111001", -- e: "1110" "1110001" -- f: "1111" ); signal R_REGS : regs_type := regs_init; -- state registers signal N_REGS : regs_type := regs_init; -- next value state regs begin assert CDWIDTH >= 5 report "assert(CDWIDTH >= 5): CDWIDTH too small" severity FAILURE; proc_regs: process (CLK) begin if CLK'event and CLK='1' then R_REGS <= N_REGS; end if; end process proc_regs; proc_next: process (R_REGS, DIN, DP) variable r : regs_type := regs_init; variable n : regs_type := regs_init; variable cano : slv4 := "0000"; variable chex : slv4 := "0000"; variable cdp : slbit := '0'; begin r := R_REGS; n := R_REGS; n.cdiv := unsigned(r.cdiv) - 1; if unsigned(r.cdiv) = 0 then n.dcnt := unsigned(r.dcnt) + 1; end if; chex := "0000"; cdp := '0'; case r.dcnt is when "00" => chex := DIN( 3 downto 0); cdp := DP(0); when "01" => chex := DIN( 7 downto 4); cdp := DP(1); when "10" => chex := DIN(11 downto 8); cdp := DP(2); when "11" => chex := DIN(15 downto 12); cdp := DP(3); when others => chex := "----"; cdp := '-'; end case; -- the logic below ensures that the anode PNP driver transistor is switched -- off 16 cycles before the cathode drivers change. This prevents 'cross -- talk' between digits due to transistor turn off delays. With no or 4 -- cycles gap one gets well visible cross talk, with 8 cycles still some -- weak cross talk. With 16 cycles (at 50MHz) none is visible. The -- turn-off delay of the anode driver PNP's this therefore larger 160 ns -- and below 320 ns. -- As consquence CDWIDTH should be at least 5, better 6. cano := "1111"; if unsigned(r.cdiv) >= 16 then cano(conv_integer(unsigned(r.dcnt))) := '0'; end if; N_REGS <= n; ANO_N <= cano; SEG_N <= not (cdp & hex2segtbl(conv_integer(unsigned(chex)))); end process proc_next; end syn;
Go to most recent revision | Compare with Previous | Blame | View Log