📄 multiio_apb.vhd
字号:
--------------------------------------------------------------------
-- Entity: MultiIO_APB
-- File: MultiIO_APB.vhd
-- Author: Thomas Ameseder, Gleichmann Electronics
-- Based on an orginal version by Manfred.Helzle@embedd.it
--
-- Description: APB Multiple digital I/O for minimal User Interface
--------------------------------------------------------------------
-- Functionality:
-- 8 LEDs, active low or high, r/w
-- dual 7Segment, active low or high, w only
-- 8 DIL Switches, active low or high, r only
-- 8 Buttons, active low or high, r only, with IRQ enables
--------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
library grlib;
use grlib.amba.all;
use grlib.stdlib.all;
use grlib.devices.all;
library gleichmann;
use gleichmann.spi.all;
use gleichmann.i2c.all;
use gleichmann.miscellaneous.all;
use gleichmann.multiio.all;
-- pragma translate_off
use std.textio.all;
-- pragma translate_on
entity MultiIO_APB is
generic (
pindex : integer := 0; -- Leon-Index
paddr : integer := 0; -- Leon-Address
pmask : integer := 16#FFF#; -- Leon-Mask
pirq : integer := 0; -- Leon-IRQ
clk_freq_in : integer := 25_000_000; -- Leons clock to calculate timings
led7act : std_logic := '0'; -- active level for 7Segment
ledact : std_logic := '0'; -- active level for LEDs
switchact : std_logic := '1'; -- active level for LED's
buttonact : std_logic := '1'; -- active level for LED's
n_switches : integer := 8; -- number of switches that are driven
n_leds : integer := 8 -- number of LEDs that are driven
);
port (
rst_n : in std_ulogic; -- global Reset, active low
clk : in std_ulogic; -- global Clock
apbi : in apb_slv_in_type; -- APB-Input
apbo : out apb_slv_out_type; -- APB-Output
MultiIO_in : in MultiIO_in_type; -- MultIO-Inputs
MultiIO_out : out MultiIO_out_type -- MultiIO-Outputs
);
end entity;
architecture Implementation of MultiIO_APB is ----------------------
constant VERSION : std_logic_vector(31 downto 0) := x"EA_04_04_06";
constant REVISION : integer := 2;
constant MUXMAX : integer := 5;
constant VCC : std_logic_vector(31 downto 0) := (others => '1');
constant GND : std_logic_vector(31 downto 0) := (others => '0');
signal Enable1ms : boolean;
signal MUXCounter : integer range 0 to MUXMAX;
signal clkgen_mclk : std_ulogic;
signal clkgen_bclk : std_ulogic;
signal clkgen_sclk : std_ulogic;
signal clkgen_lrclk : std_ulogic;
type state_t is (WAIT_FOR_SYNC,READY,WAIT_FOR_ACK);
signal state,next_state : state_t;
signal Strobe,next_Strobe : std_ulogic;
-- status signals of the i2s core for upper-level state machine
signal SampleAck, WaitForSample : std_ulogic;
signal samplereg : std_ulogic_vector(N_CODECI2SBITS-1 downto 0);
constant pconfig : apb_config_type := (
0 => ahb_device_reg (VENDOR_GLEICHMANN, GLEICHMANN_HIFC, 0, REVISION, pirq),
1 => apb_iobar(paddr, pmask)
);
type MultiIOregisters is
record
ledreg : std_logic_vector(31 downto 0); -- LEDs
led7reg : std_logic_vector(31 downto 0); -- Dual 7Segment LEDs
codecreg : std_logic_vector(31 downto 0);
codecreg2 : std_logic_vector(31 downto 0);
-- Switches in
sw_inreg : std_logic_vector(31 downto 0);
-- ASCII value of input button
btn_inreg : std_logic_vector(31 downto 0);
irqenareg : std_logic_vector(31 downto 0); -- IRQ enables for Buttons
btn_irqs : std_logic_vector(31 downto 0); -- IRQs from each Button
new_data : std_ulogic;
serviced : std_ulogic;
lcdreg : std_logic_vector(31 downto 0); -- LCD instruction
exp_in_reg : std_logic_vector(31 downto 0);
exp_out_reg : std_logic_vector(31 downto 0);
end record;
signal r, rin : MultiIOregisters; -- register sets
signal Key : std_logic_vector(7 downto 0); -- ASCII value of button
-- character representation of the key (for simulation purposes)
signal KeyVal : character;
signal OldColumnRow1 : std_logic_vector(6 downto 0); -- for key debounce
signal OldColumnRow2 : std_logic_vector(6 downto 0); -- for key debounce
begin
reg_rw : process(MUXCounter, MultiIO_in, apbi, key, r, rst_n)
variable readdata : std_logic_vector(31 downto 0); -- system bus width
variable irqs : std_logic_vector(31 downto 0); -- system IRQs width
variable v : MultiIOregisters; -- register set
-- variable new_data : std_ulogic;
begin
v := r;
-- reset registers
if rst_n = '0' then
-- lower half of LEDs on
v.ledreg := (others => '0');
v.ledreg(3 downto 0) := "1111";
v.led7reg := (others => '0');
v.led7reg(15 downto 0) := X"38_4F"; -- show "L3" Leon3 on 7Segments
v.codecreg := (others => '0');
v.codecreg2 := (others => '0');
v.irqenareg := (others => '0'); -- IRQs disable
v.btn_inreg := (others => '0');
v.sw_inreg := (others => '0');
-- new data flag off
v.new_data := '0';
v.serviced := '0';
v.lcdreg := (others => '0');
v.exp_in_reg := (others => '0');
v.exp_out_reg := (others => '0');
end if;
-- get switches and buttons
if switchact = '1' then
v.sw_inreg(N_SWITCHES-1 downto 0) := MultiIO_in.switch_in;
else
v.sw_inreg(N_SWITCHES-1 downto 0) := not MultiIO_in.switch_in;
end if;
v.btn_inreg(7 downto 0) := key;
v.btn_irqs := (others => '0');
---------------------------------------------------------------------------
-- TO BE ALTERED
---------------------------------------------------------------------------
-- set local button-IRQs
for i in 0 to v.btn_irqs'left loop
-- detect low-to-high transition
if (v.btn_inreg(i) = '1') and (r.btn_inreg(i) = '0') then
-- set local IRQs if IRQ enabled
v.btn_irqs(i) := v.btn_inreg(i) and r.irqenareg(i);
else
-- clear local IRQs
v.btn_irqs(i) := '0';
end if;
end loop;
---------------------------------------------------------------------------
-- read registers
readdata := (others => 'X');
case conv_integer(apbi.paddr(5 downto 2)) is
when 0 => readdata := r.ledreg; -- LEDs
when 1 => readdata := r.led7reg; -- seven segment
when 2 => readdata := r.codecreg; -- codec command register
when 3 => readdata := r.codecreg2; -- codec i2s register
when 4 => readdata := r.sw_inreg; -- switches
when 5 => readdata := r.btn_inreg; -- buttons
when 6 => readdata := r.irqenareg; -- IRQ enables
when 7 => readdata := conv_std_logic_vector(pirq, 32); -- IRQ#
when 8 => readdata := version; -- version
when 9 => readdata := r.lcdreg; -- LCD data
when 10 => readdata := r.exp_out_reg; -- expansion connector out
when 11 => readdata := r.exp_in_reg; -- expansion connector in
when others => null;
end case;
-- write registers
if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
case conv_integer(apbi.paddr(5 downto 2)) is
when 0 => v.ledreg :=
GND(31 downto N_LEDS) &
apbi.pwdata(N_LEDS-1 downto 0); -- write LEDs
when 1 => v.led7reg :=
GND(31 downto N_SEVSEGBITS) &
apbi.pwdata(N_SEVSEGBITS-1 downto 0); -- write 7Segment
when 2 => v.codecreg :=
GND(31 downto N_CODECBITS) &
apbi.pwdata(N_CODECBITS-1 downto 0);
when 3 => v.codecreg2 :=
GND(31 downto N_CODECI2SBITS) &
apbi.pwdata(N_CODECI2SBITS-1 downto 0);
when 6 => v.irqenareg :=
GND(31 downto N_BUTTONS) &
apbi.pwdata(N_BUTTONS-1 downto 0);
when 9 => v.lcdreg :=
GND(31 downto N_LCDBITS) &
apbi.pwdata(N_LCDBITS-1 downto 0);
-- signal that new data has arrived
v.serviced := '0';
v.new_data := '1';
when 10 => v.exp_out_reg :=
GND(31 downto N_EXPBITS/2) &
-- bit(N_EXPBITS) holds enable signal
apbi.pwdata(N_EXPBITS/2-1 downto 0);
when others => null;
end case;
end if;
irqs := (others => '0');
-- set PIRQ
for i in 0 to v.btn_irqs'left loop
-- set IRQ if button-i pressed and IRQ enabled
irqs(pirq) := irqs(pirq) or r.btn_irqs(i);
end loop;
if ledact = '1' then
MultiIO_out.led_out <= r.ledreg(N_LEDS-1 downto 0); -- not inverted
else
MultiIO_out.led_out <= not r.ledreg(N_LEDS-1 downto 0); -- inverted
end if;
-- disable seven segment and LC display by default
-- MultiIO_out.lcd_enable <= '0';
MultiIO_out.led_ca_out <= "00" xnor (led7act & led7act);
case MUXCounter is
when 0 | 1 =>
-- output logical value according to active level of the 7segment display
MultiIO_out.led_a_out <= r.led7reg(MUXCounter*8 + 0) xnor led7act;
MultiIO_out.led_b_out <= r.led7reg(MUXCounter*8 + 1) xnor led7act;
MultiIO_out.led_c_out <= r.led7reg(MUXCounter*8 + 2) xnor led7act;
MultiIO_out.led_d_out <= r.led7reg(MUXCounter*8 + 3) xnor led7act;
MultiIO_out.led_e_out <= r.led7reg(MUXCounter*8 + 4) xnor led7act;
MultiIO_out.led_f_out <= r.led7reg(MUXCounter*8 + 5) xnor led7act;
MultiIO_out.led_g_out <= r.led7reg(MUXCounter*8 + 6) xnor led7act;
MultiIO_out.led_dp_out <= r.led7reg(MUXCounter*8 + 7) xnor led7act;
-- selectively enable the current digit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -