-------------------------- -- file ADC.vhd -------------------------- -- ADC interfacing -------------------------- library ieee; use ieee.std_logic_1164.all; library work; use work.ADC_pkg.all; entity ADC is generic(datawidth: positive:= 8); port( clk: in std_logic; -- clock from FPGA Din: in std_logic; -- Output data from ADC rst: in std_logic; -- reset for whole system ack: in std_logic; -- indicate if sample is needed and when data is not needed DataRdy: out std_logic; -- tells if Data in the register is valid convst: out std_logic; -- tells the ADC to start converting sclk: buffer std_logic; -- the slower clock for the ADC Dout: out std_logic_vector(datawidth-1 downto 0); -- Sampled Data clockout:out std_logic ); end ADC; architecture interface of ADC is -- internal signal signal clk80ns, -- clock with period of 80ns RegEnable, -- indicate when to load data in register GND -- ground = 0 : std_logic; type state_type is (ready, start, start_convert, getting_input, stop_reading, data_ready); signal next_state: state_type; begin GND <= '0'; sclock:clk_divider -- the clock for the ADC is 2 times slower than the clock in FPGA port map ( clkin => clk, clkout => clk80ns ); inReg:shReg -- 8 bit shift-register generic map(reg_width=> 8) port map ( input => Din, load => RegEnable, clk => sclk, rst => rst, output => Dout ); clockout <= clk80ns; ADCcontrol:process (clk80ns) is variable count : natural range 0 to 79; begin if (rst = '0') then next_state <= ready; elsif rising_edge(clk80ns) then case next_state is when ready => count := 0; if ack = '0' then next_state <= start; else next_state <= ready; end if; when start => next_state <= start_convert; when start_convert => -- the time for power-up and conversion before the data is ready to be output in the ADC is -- 5.5us(max), so here wait for 80 (0-79) ADC's clock periods (clk80ns) will be -- 6.4us, to make sure the output is ready and is correct. if count =79 then -- if count = 79, the data is ready to be output count := 0; -- set count to 0 for the count in the next state next_state <= getting_input; else -- if not, keep counting count := count +1; next_state <= start_convert; end if; when getting_input => -- because the output of the ADC is series and 8 bit, so 8 (0-7) ADC's clock cycle -- will be needed to get the output data for one sample -- if count = 7, the sclk should be set back to 0, and stop reading data to the register if count = 7 then next_state <= stop_reading; else -- if not, keep counting count := count +1; next_state <= getting_input; end if; when stop_reading => next_state <= data_ready; when data_ready => -- ack should be change back to 0 from the main program after the data in the register -- is being taked if (ack = '1') then next_state <= ready; else next_state <= data_ready; end if; end case; end if; end process ADCcontrol; with next_state select sclk <= clk80ns when getting_input, '0' when others; with next_state select convst <= '1' when start|start_convert, '0' when others; with next_state select DataRdy <= '1' when data_ready, '0' when others; with next_state select RegEnable <= '1' when getting_input, '0' when others; end interface;