180 lines
5.0 KiB
VHDL
180 lines
5.0 KiB
VHDL
-- See the file "LICENSE" for the full license governing this code. --
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use work.lt16x32_global.all;
|
|
use work.wishbone.all;
|
|
use work.config.all;
|
|
|
|
entity wb_segment_adv is
|
|
generic(
|
|
memaddr : generic_addr_type; --:= CFG_BADR_SEG;
|
|
addrmask : generic_mask_type --:= CFG_MADR_SEG;
|
|
);
|
|
port(
|
|
clk : in std_logic;
|
|
rst : in std_logic;
|
|
wslvi : in wb_slv_in_type;
|
|
wslvo : out wb_slv_out_type;
|
|
|
|
anodes : out std_logic_vector(7 downto 0);
|
|
cathodes : out std_logic_vector(7 downto 0)
|
|
);
|
|
end wb_segment_adv;
|
|
|
|
architecture Behavioral of wb_segment_adv is
|
|
|
|
signal ack : std_logic;
|
|
|
|
signal hex_register : std_logic_vector(63 downto 0);
|
|
signal data_out : std_logic_vector(63 downto 0);
|
|
signal data_in : std_logic_vector(31 downto 0);
|
|
signal data_in_changed : std_logic;
|
|
|
|
signal hex : std_logic_vector(4 downto 0);
|
|
|
|
signal timer_overflow : std_logic;
|
|
signal overflow_counter : integer range 0 to 7;
|
|
|
|
component hex2physical
|
|
port(
|
|
hex : in std_logic_vector(4 downto 0);
|
|
cathodes : out std_logic_vector(7 downto 0)
|
|
);
|
|
end component;
|
|
|
|
component simple_timer
|
|
generic(
|
|
timer_start : std_logic_vector (31 downto 0)
|
|
);
|
|
port(
|
|
clk : in std_logic;
|
|
rst : in std_logic;
|
|
timer_overflow : out std_logic
|
|
);
|
|
end component;
|
|
|
|
begin
|
|
|
|
converter : hex2physical
|
|
port map(
|
|
hex => hex,
|
|
cathodes => cathodes
|
|
);
|
|
|
|
timer: simple_timer
|
|
-- generic map (timer_start => x"00000008") -- for simulation
|
|
generic map (timer_start => x"00000F00") -- for board
|
|
port map(
|
|
clk => clk,
|
|
rst => rst,
|
|
timer_overflow => timer_overflow
|
|
);
|
|
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if rst = '1' then
|
|
ack <= '0';
|
|
data_out <= (others=>'0');
|
|
data_in <= (others=>'0');
|
|
data_in_changed <= '0';
|
|
else
|
|
data_out <= (others=>'0');
|
|
data_in <= (others=>'0');
|
|
data_in_changed <= '0';
|
|
|
|
if wslvi.stb = '1' and wslvi.cyc = '1' then
|
|
if wslvi.we='0' then
|
|
data_out <= hex_register;
|
|
else
|
|
-- Write enable
|
|
data_in <= dec_wb_dat(wslvi.sel,wslvi.dat);
|
|
data_in_changed <= '1';
|
|
end if;
|
|
|
|
if ack = '0' then
|
|
ack <= '1';
|
|
else
|
|
ack <= '0';
|
|
end if;
|
|
else
|
|
ack <= '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process(clk)
|
|
variable v_data : std_logic_vector(3 downto 0);
|
|
variable v_off : std_logic;
|
|
variable v_write : std_logic;
|
|
variable v_clear : std_logic;
|
|
variable v_shift : std_logic;
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if rst = '1' then
|
|
hex_register <= (others=>'0');
|
|
else
|
|
if data_in_changed = '1' and ack = '1' then -- only check if ack was just raised
|
|
v_data := data_in(3 downto 0);
|
|
v_off := data_in(4);
|
|
v_write := data_in(8);
|
|
v_clear := data_in(16);
|
|
v_shift := data_in(24);
|
|
|
|
-- No special care has to be taken to support
|
|
-- writing and shifting at the same time.
|
|
|
|
if v_shift = '1' then
|
|
hex_register(63 downto 56) <= (others => '0');
|
|
hex_register(55 downto 0) <= hex_register(63 downto 8);
|
|
end if;
|
|
|
|
if v_write = '1' then
|
|
hex_register(59 downto 56) <= v_data;
|
|
hex_register(60) <= not v_off; -- unclear if this should only be set when write is 1
|
|
end if;
|
|
|
|
if v_clear = '1' then
|
|
hex_register <= (others => '0');
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if rst = '1' then
|
|
hex <= hex_register(4 downto 0);
|
|
anodes <= (others => not '0');
|
|
overflow_counter <= 0;
|
|
else
|
|
if timer_overflow = '1' then
|
|
if overflow_counter = 7 then
|
|
overflow_counter <= 0;
|
|
else
|
|
overflow_counter <= overflow_counter + 1;
|
|
end if;
|
|
|
|
anodes <= (others => not '0');
|
|
anodes(overflow_counter) <= not '1';
|
|
|
|
hex <= hex_register(overflow_counter * 8 + 4 downto overflow_counter * 8);
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
wslvo.dat <=
|
|
data_out(31 downto 0) when wslvi.adr(2) = '0' else
|
|
data_out(63 downto 32) when wslvi.adr(2) = '1';
|
|
|
|
wslvo.ack <= ack;
|
|
wslvo.wbcfg <= wb_membar(memaddr, addrmask);
|
|
|
|
end Behavioral;
|