library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Device is
port (
-- SRAM address, data, WE, CE
ram_a: out std_logic_vector(14 downto 0);
ram_ad: out std_logic_vector(15 downto 0);
ram_we: out std_logic;
ram_ce: out std_logic;
-- ADC data output
adc_d: in std_logic_vector(7 downto 0);
-- main clock generated by MCU
clk16: in std_logic;
-- divided clock
clk_out: buffer std_logic;
-- open drain output with external pull up resistor. Connected to MCU
start: inout std_logic;
-- reset. Connected to MCU
reset: in std_logic
);
end Device;
architecture b of Device is
type T_STATE is (STOPPED, STARTING, DUMMY_PERIOD, SAMPLING, FINISHING, WAITING_FOR_STOP);
type T_SAVINGSTATE is (NOTSAVING, SAVING, FINISHINGSAVING);
signal cnt: unsigned(9 downto 0);
signal address: std_logic_vector(14 downto 0);
signal state: T_STATE := STOPPED;
signal savingstate: T_SAVINGSTATE := SAVING;
-- timing for state machine:
constant DUMMY_CLOCKS: integer := 97;
constant START_SAVING_CLOCKS: integer := DUMMY_CLOCKS + 5;
constant STOP_SAMPLING_CLOCKS: integer := DUMMY_CLOCKS + 512;
constant FINISH_SAVING_CLOCKS: integer := START_SAVING_CLOCKS + 512;
constant STOP_SAVING_CLOCKS: integer := FINISH_SAVING_CLOCKS + 1;
begin
process (clk16, clk_out, reset)
begin
if reset = '0' then
address <= (others => '0');
state <= STOPPED;
savingstate <= NOTSAVING;
ram_a <= (others => 'Z');
ram_ad <= (others => 'Z');
ram_ce <= 'Z';
ram_we <= 'Z';
clk_out <= '0';
start_pulse <= '0';
start <= 'Z';
else
if rising_edge(clk16) then
clk_out <= not clk_out;
end if;
if falling_edge(clk16) then
if savingstate = SAVING then
if clk_out = '1' then
ram_a <= address;
ram_ad(7 downto 0) <= adc_d;
else
address <= unsigned(address) + 1;
ram_ad(15 downto 8) <= adc_d;
end if;
elsif savingstate = NOTSAVING then
ram_a <= (others => 'Z');
ram_ad <= (others => 'Z');
end if;
end if;
if rising_edge(clk_out) then
case state is
when STOPPED =>
if start = '0' then -- MCU started the job by pulling the line low
start <= '0'; -- pull it low to tell MCU the job is in progress
state <= STARTING;
end if;
when STARTING =>
cnt <= (others => '0');
state <= DUMMY_PERIOD;
when DUMMY_PERIOD =>
cnt <= cnt + 1;
if cnt = DUMMY_CLOCKS then
state <= SAMPLING;
end if;
when SAMPLING =>
cnt <= cnt + 1;
if cnt = START_SAVING_CLOCKS then
savingstate <= SAVING;
elsif cnt = STOP_SAMPLING_CLOCKS then
state <= FINISHING;
end if;
when FINISHING =>
cnt <= cnt + 1;
if cnt = FINISH_SAVING_CLOCKS then
savingstate <= FINISHINGSAVING;
elsif cnt = STOP_SAVING_CLOCKS then
savingstate <= NOTSAVING;
state <= WAITING_FOR_STOP;
start <= 'Z'; -- job done, release the line
end if;
when WAITING_FOR_STOP =>
cnt <= cnt + 1;
if cnt = STOP_SAVING_CLOCKS + 100 then
state <= STOPPED;
end if;
end case;
end if;
if savingstate = SAVING then
ram_ce <= cis_cp;
elsif savingstate = FINISHINGSAVING then
ram_ce <= '1';
else
ram_ce <= 'Z';
end if;
end if;
end process;
end b;
There is my MAX V that implements this code, ADC that converts data from sensor, MCU and SRAM.
MCU resets or starts the job (reset, start),.
When started, CPLD starts reading data from ADC's 8 bit data bus and saves it to SRAM which has 16 bit data bus.