-------------------------------------------------------------------------------------------------100
|
-------------------------------------------------------------------------------------------------100
|
--| Modular Oscilloscope
|
--| Modular Oscilloscope
|
--| UNSL - Argentine
|
--| UNSL - Argentine
|
--|
|
--|
|
--| File: output_manager.vhd
|
--| File: output_manager.vhd
|
--| Version: 0.3
|
--| Version: 0.31
|
--| Tested in: Actel A3PE1500
|
--| Tested in: Actel A3PE1500
|
--|-------------------------------------------------------------------------------------------------
|
--|-------------------------------------------------------------------------------------------------
|
--| Description:
|
--| Description:
|
--| CONTROL - Output manager
|
--| CONTROL - Output manager
|
--| This is a pseudo buffer, wich reads a memory incrementaly under certain parameters.
|
--| This is a pseudo buffer, wich reads a memory incrementaly under certain parameters.
|
--|
|
--|
|
--|-------------------------------------------------------------------------------------------------
|
--|-------------------------------------------------------------------------------------------------
|
--| File history:
|
--| File history:
|
--| 0.1 | jun-2009 | First testing
|
--| 0.1 | jun-2009 | First testing
|
--| 0.2 | jul-2009 | Two levels internal buffer
|
--| 0.2 | jul-2009 | Two levels internal buffer
|
--| 0.3 | jul-2009 | One level internal buffer and only one clock
|
--| 0.3 | jul-2009 | One level internal buffer and only one clock
|
|
--| 0.31 | jul-2009 | Internal WE signals
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
--| Copyright ® 2009, Facundo Aguilera.
|
--| Copyright © 2009, Facundo Aguilera.
|
--|
|
--|
|
--| This VHDL design file is an open design; you can redistribute it and/or
|
--| This VHDL design file is an open design; you can redistribute it and/or
|
--| modify it and/or implement it after contacting the author.
|
--| modify it and/or implement it after contacting the author.
|
|
|
--| Wishbone Rev. B.3 compatible
|
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
|
|
|
|
|
--==================================================================================================
|
-- TODO
|
-- TODO
|
-- Config WE signals
|
-- · Spped up address_counter (with Actel SmartGen).
|
|
--==================================================================================================
|
|
|
-- This first release
|
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
use IEEE.NUMERIC_STD.ALL;
|
use IEEE.NUMERIC_STD.ALL;
|
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
entity output_manager is
|
entity output_manager is
|
generic(
|
generic(
|
MEM_ADD_WIDTH: integer := 14
|
MEM_ADD_WIDTH: integer := 14
|
);
|
);
|
port(
|
port(
|
------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------
|
-- MASTER (to memory)
|
-- MASTER (to memory)
|
DAT_I_mem: in std_logic_vector (15 downto 0);
|
DAT_I_mem: in std_logic_vector (15 downto 0);
|
--DAT_O_mem: out std_logic_vector (15 downto 0);
|
--DAT_O_mem: out std_logic_vector (15 downto 0);
|
ADR_O_mem: out std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
ADR_O_mem: out std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
CYC_O_mem: out std_logic;
|
CYC_O_mem: out std_logic;
|
STB_O_mem: out std_logic;
|
STB_O_mem: out std_logic;
|
ACK_I_mem: in std_logic ;
|
ACK_I_mem: in std_logic ;
|
WE_O_mem: out std_logic;
|
WE_O_mem: out std_logic;
|
|
|
------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------
|
-- SLAVE (to I/O ports)
|
-- SLAVE (to I/O ports)
|
--DAT_I_port: in std_logic_vector (15 downto 0);
|
--DAT_I_port: in std_logic_vector (15 downto 0);
|
DAT_O_port: out std_logic_vector (15 downto 0);
|
DAT_O_port: out std_logic_vector (15 downto 0);
|
--ADR_I_port: in std_logic_vector (7 downto 0);
|
--ADR_I_port: in std_logic_vector (7 downto 0);
|
CYC_I_port: in std_logic;
|
CYC_I_port: in std_logic;
|
STB_I_port: in std_logic;
|
STB_I_port: in std_logic;
|
ACK_O_port: out std_logic ;
|
ACK_O_port: out std_logic ;
|
WE_I_port: in std_logic;
|
WE_I_port: in std_logic;
|
|
|
|
|
------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------
|
-- Common signals
|
-- Common signals
|
RST_I: in std_logic;
|
RST_I: in std_logic;
|
CLK_I: in std_logic;
|
CLK_I: in std_logic;
|
|
|
------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------
|
-- Internal
|
-- Internal
|
-- reset counter to initial address, or load it
|
-- reset counter to initial address, or load it
|
load: in std_logic;
|
load: in std_logic;
|
-- start count from the actual address ('0' means pause, '1' means continue)
|
-- start count from the actual address ('0' means pause, '1' means continue)
|
enable: in std_logic;
|
enable: in std_logic;
|
-- buffer starts and ends here
|
-- buffer starts and ends here
|
initial_address: in std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
initial_address: in std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
-- when the buffer arrives here, address is changed to 0 (buffer size)
|
-- when the buffer arrives here, address is changed to 0 (buffer size)
|
final_address: in std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
final_address: in std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
-- address wich is being writed by control
|
-- address wich is being writed by control
|
-- stop_address: in std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
stop_address: in std_logic_vector (MEM_ADD_WIDTH - 1 downto 0);
|
-- it is set when communication ends and remains until next restart or actual address change
|
-- it is set when communication ends and remains until next restart or actual address change
|
finish: out std_logic
|
finish: out std_logic
|
|
|
|
|
);
|
);
|
end entity output_manager;
|
end entity output_manager;
|
|
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------
|
architecture ARCH11 of output_manager is
|
architecture ARCH11 of output_manager is
|
|
|
|
|
|
|
|
|
type DataStatusType is (
|
type DataStatusType is (
|
RESET,
|
RESET,
|
INIT, -- when restartet
|
INIT, -- when restartet
|
READY, -- data available to be read
|
READY, -- data available to be read
|
READ -- data was read from port, read next from memory
|
READ -- data was read from port, read next from memory
|
);
|
);
|
|
|
signal data_status: DataStatusType; -- comunicates status between both ports
|
signal data_status: DataStatusType; -- comunicates status between both ports
|
|
|
signal address_counter: std_logic_vector(MEM_ADD_WIDTH - 1 downto 0);
|
signal address_counter: std_logic_vector(MEM_ADD_WIDTH - 1 downto 0);
|
signal data: std_logic_vector(15 downto 0);
|
signal data: std_logic_vector(15 downto 0);
|
signal enable_read: std_logic;
|
signal enable_read: std_logic;
|
signal s_finish: std_logic;
|
signal s_finish: std_logic;
|
|
|
|
|
begin
|
begin
|
|
|
--------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------
|
-- Data status resolution
|
-- Data status resolution
|
|
|
P_status: process(CLK_I, RST_I, load, WE_I_port)
|
P_status: process(CLK_I, RST_I, load, WE_I_port)
|
begin
|
begin
|
|
|
if (CLK_I'event and CLK_I = '1') then
|
if (CLK_I'event and CLK_I = '1') then
|
if RST_I = '1' or load = '1' then
|
if RST_I = '1' or load = '1' then
|
data_status <= RESET;
|
data_status <= RESET;
|
else
|
else
|
case data_status is
|
case data_status is
|
when RESET =>
|
when RESET =>
|
|
|
data_status <= INIT;
|
data_status <= INIT;
|
|
|
when INIT =>
|
when INIT =>
|
|
|
if ACK_I_mem = '1' and enable_read = '1' then
|
if ACK_I_mem = '1' and enable_read = '1' then
|
data_status <= READY;
|
data_status <= READY;
|
end if;
|
end if;
|
|
|
|
|
when READ =>
|
when READ =>
|
|
|
if ACK_I_mem = '1' and enable_read = '1' and (STB_I_port /= '1' or CYC_I_port /= '1' or
|
if ACK_I_mem = '1' and enable_read = '1' and (STB_I_port /= '1' or CYC_I_port /= '1' or
|
WE_I_port /= '0')
|
WE_I_port /= '0')
|
then
|
then
|
data_status <= READY;
|
data_status <= READY;
|
end if;
|
end if;
|
-- STB_I_port /= '1' or CYC_I_port /= '1': forwarding
|
-- STB_I_port /= '1' or CYC_I_port /= '1': forwarding
|
|
|
when others => -- (when READY)
|
when others => -- (when READY)
|
|
|
if STB_I_port = '1' and CYC_I_port = '1' and WE_I_port = '0' then
|
if STB_I_port = '1' and CYC_I_port = '1' and WE_I_port = '0' then
|
data_status <= READ;
|
data_status <= READ;
|
end if;
|
end if;
|
|
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
end process;
|
end process;
|
|
|
|
|
--------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------
|
-- Data read
|
-- Data read
|
ADR_O_mem <= address_counter;
|
ADR_O_mem <= address_counter;
|
s_finish <= '1' when address_counter = initial_address and data_status /= INIT else
|
s_finish <= '1' when address_counter = initial_address and data_status /= INIT else
|
'0';
|
'0';
|
enable_read <= enable and not(s_finish);
|
enable_read <= '1' when enable = '1' and s_finish = '0' and address_counter /= stop_address
|
|
else '0';
|
|
|
finish <= s_finish;
|
finish <= s_finish;
|
WE_O_mem <= '0' ;
|
WE_O_mem <= '0' ;
|
|
|
|
|
|
|
P_read: process(CLK_I, data_status, initial_address, address_counter, data, enable_read,
|
P_read: process(CLK_I, data_status, initial_address, address_counter, data, enable_read,
|
ACK_I_mem, WE_I_port)
|
ACK_I_mem, WE_I_port)
|
begin
|
begin
|
|
|
|
|
-- Clocked signals
|
-- Clocked signals
|
if (CLK_I'event and CLK_I = '1') then
|
if (CLK_I'event and CLK_I = '1') then
|
case data_status is
|
case data_status is
|
|
|
when RESET =>
|
when RESET =>
|
|
|
data <= (others => '0');
|
data <= (others => '0');
|
address_counter <= initial_address;
|
address_counter <= initial_address;
|
|
|
when READY =>
|
when READY =>
|
|
|
if enable_read = '1' and ACK_I_mem = '1' and CYC_I_port = '1' and STB_I_port = '1' then
|
if enable_read = '1' and ACK_I_mem = '1' and CYC_I_port = '1' and STB_I_port = '1' then
|
-- (forwarding)
|
-- (forwarding)
|
data <= DAT_I_mem;
|
data <= DAT_I_mem;
|
if address_counter < final_address then
|
if address_counter < final_address then
|
address_counter <= address_counter + 1;
|
address_counter <= address_counter + 1;
|
else
|
else
|
address_counter <= (others => '0');
|
address_counter <= (others => '0');
|
end if;
|
end if;
|
else
|
else
|
data <= data;
|
data <= data;
|
address_counter <= address_counter;
|
address_counter <= address_counter;
|
end if;
|
end if;
|
|
|
when others => -- (when INIT or READ)
|
when others => -- (when INIT or READ)
|
|
|
if enable_read = '1' and ACK_I_mem = '1' then
|
if enable_read = '1' and ACK_I_mem = '1' then
|
data <= DAT_I_mem;
|
data <= DAT_I_mem;
|
if address_counter < final_address then
|
if address_counter < final_address then
|
address_counter <= address_counter + 1;
|
address_counter <= address_counter + 1;
|
else
|
else
|
address_counter <= (others => '0');
|
address_counter <= (others => '0');
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
end case;
|
end case;
|
end if;
|
end if;
|
|
|
-- Cominational signals
|
-- Cominational signals
|
|
|
case data_status is
|
case data_status is
|
when RESET =>
|
when RESET =>
|
|
|
STB_O_mem <= '0';
|
STB_O_mem <= '0';
|
CYC_O_mem <= '0';
|
CYC_O_mem <= '0';
|
|
|
when READY =>
|
when READY =>
|
|
|
if enable_read = '1' and CYC_I_port = '1' and STB_I_port = '1' and WE_I_port = '0' then
|
if enable_read = '1' and CYC_I_port = '1' and STB_I_port = '1' and WE_I_port = '0' then
|
-- (forwarding)
|
-- (forwarding)
|
STB_O_mem <= '1';
|
STB_O_mem <= '1';
|
CYC_O_mem <= '1';
|
CYC_O_mem <= '1';
|
else
|
else
|
STB_O_mem <= '0';
|
STB_O_mem <= '0';
|
CYC_O_mem <= '0';
|
CYC_O_mem <= '0';
|
end if;
|
end if;
|
|
|
when others => -- (when INIT or READ)
|
when others => -- (when INIT or READ)
|
|
|
if enable_read = '1' then
|
if enable_read = '1' then
|
STB_O_mem <= '1';
|
STB_O_mem <= '1';
|
CYC_O_mem <= '1';
|
CYC_O_mem <= '1';
|
else
|
else
|
STB_O_mem <= '0';
|
STB_O_mem <= '0';
|
CYC_O_mem <= '0';
|
CYC_O_mem <= '0';
|
end if;
|
end if;
|
|
|
end case;
|
end case;
|
|
|
|
|
end process;
|
end process;
|
|
|
|
|
|
|
--------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------
|
-- Read from port interface
|
-- Read from port interface
|
ACK_O_port <= '1' when (CYC_I_port = '1' and STB_I_port = '1' and WE_I_port = '0') and
|
ACK_O_port <= '1' when (CYC_I_port = '1' and STB_I_port = '1' and WE_I_port = '0') and
|
(data_status = READY or
|
(data_status = READY or
|
(data_status = READ and ACK_I_mem = '1' and enable_read = '1' )) else
|
(data_status = READ and ACK_I_mem = '1' and enable_read = '1' )) else
|
'0';
|
'0';
|
-- data_status = READ and ACK_I_mem = '1' and enable_read = '1': forwarding
|
-- data_status = READ and ACK_I_mem = '1' and enable_read = '1': forwarding
|
|
|
DAT_O_port <= data;
|
DAT_O_port <= data;
|
|
|
|
|
|
|
|
|
|
|