141 lines
3.7 KiB
VHDL
141 lines
3.7 KiB
VHDL
--==============================================================================
|
|
--
|
|
-- AHB general purpose input/outputs
|
|
--
|
|
-- Provides "ioNb" input/output signals .
|
|
--
|
|
--------------------------------------------------------------------------------
|
|
--
|
|
-- Write registers
|
|
--
|
|
-- 00, data register receives the values to drive the output lines.
|
|
-- 01, output enable register defines the signal direction:
|
|
-- when '1', the direction is "out".
|
|
--
|
|
--------------------------------------------------------------------------------
|
|
--
|
|
-- Read registers
|
|
-- 00, data register provides the values detected on the lines.
|
|
--
|
|
ARCHITECTURE studentVersion OF ahbGpio IS
|
|
|
|
signal addresses: unsigned(hAddr'range);
|
|
signal bRead: std_ulogic;
|
|
signal bWrite: std_ulogic;
|
|
signal bDone: std_ulogic;
|
|
|
|
|
|
BEGIN
|
|
|
|
process(hReset_n, hClk) begin
|
|
if hReset_n = '0' then
|
|
-- AHB-Lite
|
|
--hRData <= (OTHERS => 'Z');
|
|
hRData <= (OTHERS => '0');
|
|
hReady <= '1';
|
|
hResp <= '0';
|
|
|
|
-- Out
|
|
ioOut <= (OTHERS => '0');
|
|
ioEn <= (OTHERS => '0');
|
|
|
|
addresses <= (OTHERS => '0');
|
|
bRead <= '0';
|
|
bWrite <= '0';
|
|
bDone <= '0';
|
|
elsif rising_edge(hClk) then
|
|
if hSel = '1' then
|
|
bWrite <= hWrite;
|
|
bRead <= not hWrite;
|
|
addresses <= hAddr;
|
|
hReady <= '0';
|
|
bDone <= '0';
|
|
else
|
|
bWrite <= '0';
|
|
bRead <= '0';
|
|
end if;
|
|
|
|
if bRead = '1' and bWrite = '0' then
|
|
-------------------------------------------------------------------------
|
|
-- READ
|
|
-------------------------------------------------------------------------
|
|
|
|
if addresses = "00" then
|
|
-- ##### Read data register #####
|
|
--hRData <= unsigned(resize(ioIn, ioNb));
|
|
for i in 0 to ioNb-1 loop
|
|
hRData(i) <= ioIn(i);
|
|
end loop;
|
|
bDone <= '1';
|
|
|
|
elsif addresses = "01" then
|
|
report "@@@@@@@@@@ Not possible to change output in READ mode @@@@@@@@@@" severity error;
|
|
|
|
end if;
|
|
|
|
elsif bRead = '0' and bWrite = '1' then
|
|
-------------------------------------------------------------------------
|
|
-- WRITE
|
|
-------------------------------------------------------------------------
|
|
|
|
if addresses = "00" then
|
|
-- ##### Write data register #####
|
|
--ioOut <= resize(std_ulogic_vector(hWData), ioNb);
|
|
for i in 0 to ioNb-1 loop
|
|
ioOut(i) <= hWData(i);
|
|
end loop;
|
|
bDone <= '1';
|
|
|
|
elsif addresses = "01" then
|
|
-- ##### Write direction register #####
|
|
--ioEn <= hWData;
|
|
for i in 0 to ioNb-1 loop
|
|
ioEn(i) <= hWData(i);
|
|
end loop;
|
|
bDone <= '1';
|
|
|
|
end if;
|
|
|
|
elsif bRead = '1' and bWrite = '1' then
|
|
-------------------------------------------------------------------------
|
|
-- SHOULD NEVER HAPPEN
|
|
-------------------------------------------------------------------------
|
|
report "@@@@@@@@@@ READ and WRITE can't happened in same time @@@@@@@@@@" severity error;
|
|
|
|
end if;
|
|
|
|
if (ioIn and ioEn) = (ioEn and ioOut) then
|
|
hResp <= '0';
|
|
else
|
|
hResp <= '1';
|
|
end if;
|
|
|
|
if bDone = '1' then
|
|
--hRData <= (OTHERS => 'Z');
|
|
bDone <= '0';
|
|
hReady <= '1';
|
|
end if;
|
|
|
|
end if;
|
|
|
|
for i in (ioNb-1) downto 0 loop
|
|
if (ioEn(i) and ioIn(i)) /= (ioEn(i) and ioOut(i)) then
|
|
--ioEn(i) <= '0';
|
|
report "an output was in conflict" severity note;
|
|
end if;
|
|
end loop;
|
|
|
|
end process;
|
|
|
|
-- AHB-Lite
|
|
-- hRData <= (OTHERS => '0');
|
|
-- hReady <= '0';
|
|
-- hResp <= '0';
|
|
|
|
-- Out
|
|
-- ioOut <= (OTHERS => '0');
|
|
-- ioEn <= (OTHERS => '0');
|
|
|
|
END ARCHITECTURE studentVersion;
|
|
|