--------------------------------------------------------------------------------- -- -- file: adcinfo.vhd -- purpose: to test the reception of a serial analog-to-digital convertor (ADC) -- function: upon a pb1 being pressed, a cs signal is sent high, then low, -- to the ADC. The ADC then clocks out 2 garbage bits, 1 Null bits, -- 12 sampled data bits -MSB first, then 12 bits of the same data LSB first -- This program latches data at the proper throughput from the ADC and -- displays it using the hex 7 segment displays -- -- adc1_buffer(0) = MSB of actual data stream -- adc1_buffer(1) = Next data bit of actual data stream -- -- adc1_buffer(0) is connected to segment A on the first flex 7 digit -- adc1_buffer(1) is connected to segment B on the first flex 7 digit -- -- The 2 Flex 7 digit displays can only display 16 bits so -- only 16 bits of the ADC stream are represented (should be more than -- sufficient for a 12 bit ADC) -- -- timer1 = whole bit timer (controls when next bit state is represented) -- timer2 = half bit timer (latching occurs on the middle of the bit) -- -- latchdata : makes sure data is latched only once -- (at the middle of a whole bit length) --------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; entity adcinfo is port ( clock : in std_logic; pb1 : in std_logic; cs : out std_logic; dclock : out std_logic; adc1 : in std_logic; adc1_buffer : buffer std_logic_vector(5 downto 0); -- adc2_buffer : buffer std_logic_vector(5 downto 0); -- compass_in : in std_logic_vector(3 downto 0); -- compass_buffer : buffer std_logic_vector(3 downto 0); signal timer_reset1, timer_start1, timer_running1, timer_running2 : buffer std_logic; signal restart_timer : buffer std_logic; signal delaystate : buffer std_logic_vector(3 downto 0); latchdata : buffer std_logic; bitcount : buffer std_logic_vector(3 downto 0); -- lights : out std_logic_vector(3 downto 0); led1 : out std_logic_vector(11 downto 0) ); end entity adcinfo; architecture behaviour of adcinfo is COMPONENT lpm_add_sub GENERIC (LPM_WIDTH: POSITIVE; LPM_REPRESENTATION: STRING := "SIGNED"; LPM_DIRECTION: STRING := "UNUSED"; LPM_HINT: STRING := "UNUSED"; LPM_PIPELINE: INTEGER := 0; LPM_TYPE: STRING := "L_ADD_SUB"); PORT (dataa, datab: IN STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0); aclr: IN STD_LOGIC := '0'; clock: IN STD_LOGIC := '0'; cin: IN STD_LOGIC := '0'; add_sub: IN STD_LOGIC := '1'; result: OUT STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0); cout, overflow: OUT STD_LOGIC); END COMPONENT; component timer generic( clock_period_multiplier: positive := 25600; -- this times a 512 kHz clock is 50 ms internal_counter_bit_width: positive := 24 -- number of bits wide the counter will be ); port ( clock: in std_logic; reset: in std_logic; start: in std_logic; running: out std_logic); end component; component makeclks generic( M : positive := 3; N : positive := 5; P : positive := 8); port(clock : in std_logic; clocko1, clocko2, datclk : out std_logic; store1, store2, store3 : buffer std_logic); end component; component debounce port ( inp, clk: in std_logic; outp: out std_logic ); end component; -- component decoder_7seg -- port ( -- input: in std_logic_vector(3 downto 0); -- led: out std_logic_vector(6 downto 0)); -- end component; -- timer signals and timer control signals --signal timer_reset1, timer_start1, timer_running1 : std_logic; --signal restart_timer : std_logic; -- lpm counter signals --signal count_en1, internal_reset : std_logic; signal count : std_logic_vector(7 downto 0); -- decoder signals for hex 7 segment displays signal decoderin1, decoderin2 : std_logic_vector(3 downto 0); signal decoderout1, decoderout2 : std_logic_vector(6 downto 0); -- unconnected/unused ports signal nowhere1, nowhere2 : std_logic; signal tclock : std_logic; signal pb1_deb : std_logic; -- have bitcount to increment by 1 signal onebit : std_logic_vector(3 downto 0); signal addone : std_logic_vector(3 downto 0); begin addsub : lpm_add_sub generic map(LPM_WIDTH => 4) port map( dataa => bitcount, datab => onebit, result => addone); debouncepb1 : debounce port map( inp => pb1, clk => clock, outp => pb1_deb); wholebittimer1 : timer -- by simulation, run time on timer always -- extends by 4 extra clock periods -- i.e. multiplier =5 , clock = 40ns period -- timerunning = 5*40ns + 4*40ns = 360ns generic map( clock_period_multiplier => 13, -- multiplier = 25000000 for 1 sec. delay internal_counter_bit_width => 17) port map(clock => clock, reset => timer_reset1, start => timer_start1, running => timer_running1); latchingtimer : timer generic map( clock_period_multiplier => 12, -- multiplier = 25000000 for 1 sec. delay internal_counter_bit_width => 15) port map(clock => clock, reset => timer_reset1, start => timer_start1, running => timer_running2); makeclock2 : makeclks -- multiplier requires a clock period to operate -- i.e. for a 40ns period input clock, M=3 creates a -- (40ns + 40ns) *3 = 240ns period clock generic map( M => 10, --M=10 period=800ns N => 4, P => 1) -- 125000 -- 4 * 80ns => 3.125 MHz clock for DCLOCK port map(clock => clock, clocko1 => dclock, clocko2 => tclock, datclk => nowhere2); onebit <= "0001"; -------------------- Explanation of delaystate signal ---------------------- -- Potential Problem: -- System checks if the timer has stopped running -- No -> do nothing (restart timer = 0) -- Yes -> restart timer ( = '1' ) -- -- The problem is that after timer_start is set to '1', it takes -- a clock pulse for the timer to actually start running -- If the system latches on timer_running = 0 at this time, it thinks -- the timer is finished and must be restarted - but we don't want to -- restart the timer! -- -- Solution: A signal delaystate -- System checks if the timer has stopped running AND delay state = 3 -- No -> do nothing (restart timer = 0) -- Yes -> restart timer (= '1') ------------------------------------------------------------------------------ resettime : process (pb1_deb, clock) is begin if clock'event and clock = '1' then if pb1_deb = '1' or (bitcount = "1000") then timer_start1 <= '0'; timer_reset1 <= '1'; cs <= '1'; bitcount <= "0000"; delaystate <= "1001"; -- bunch of delaystates so that cs is long enough -- to be recognizable (150ns) by the ADC -- (probably not needed but I want to be sure) elsif delaystate = "1001" then delaystate <= "1000"; elsif delaystate = "1000" then delaystate <= "0111"; elsif delaystate = "0111" then delaystate <= "0110"; elsif delaystate = "0110" then delaystate <= "0001"; elsif pb1_deb = '0' and delaystate = "0001" then cs <= '0'; timer_start1 <= '1'; timer_reset1 <= '0'; delaystate <= "0010"; elsif delaystate = "0010" then delaystate <= "0011"; elsif restart_timer = '1' then timer_start1 <= '0'; timer_reset1 <= '1'; bitcount <= addone; delaystate <= "0001"; else end if; end if; end process resettime; getadinfo : process (clock) is begin if clock'event and clock = '1' then case bitcount is when "0000" => if pb1_deb = '1' then latchdata <= '0'; adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then latchdata <= '1'; else restart_timer <= '0'; end if; when "0001" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then latchdata <= '1'; else restart_timer <= '0'; end if; when "0010" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(0) <= adc1; -- adc2_buffer(0) <= adc2; latchdata <= '1'; else restart_timer <= '0'; end if; when "0011" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(1) <= adc1; -- adc2_buffer(1) <= adc2; latchdata <= '1'; else restart_timer <= '0'; end if; when "0100" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(2) <= adc1 after 10 ns; -- adc2_buffer(2) <= adc2 after 10 ns; latchdata <= '1'; else restart_timer <= '0'; end if; when "0101" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(3) <= adc1 after 10 ns; -- adc2_buffer(3) <= adc2 after 10 ns; latchdata <= '1'; else restart_timer <= '0'; end if; when "0110" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(4) <= adc1; -- adc2_buffer(4) <= adc2; latchdata <= '1'; else restart_timer <= '0'; end if; when "0111" => if pb1_deb = '1' then adc1_buffer <= "000000"; -- adc2_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(5) <= adc1; -- adc2_buffer(5) <= adc2; -- compass_buffer <= compass_in; latchdata <= '1'; else restart_timer <= '0'; end if; when others => led1(0) <= not adc1_buffer(0); led1(1) <= not adc1_buffer(1); led1(2) <= not adc1_buffer(2); led1(3) <= not adc1_buffer(3); led1(4) <= not adc1_buffer(4); led1(5) <= not adc1_buffer(5); led1(6) <= '1'; led1(7) <= '1'; led1(8) <= '1'; led1(9) <= '1'; led1(10) <= '1'; led1(11) <= '1'; -- led2(0) <= not adc2_buffer(0); -- led2(1) <= not adc2_buffer(1); -- led2(2) <= not adc2_buffer(2); -- led2(3) <= not adc2_buffer(3); -- led2(4) <= not adc2_buffer(4); -- led2(5) <= not adc2_buffer(5); -- led2(6) <= '1'; -- led2(7) <= '1'; -- led2(8) <= '1'; -- led2(9) <= '1'; -- led2(10) <= '1'; -- led2(11) <= '1'; -- lights(3) <= not compass_buffer(3); -- lights(2) <= not compass_buffer(2); -- lights(1) <= not compass_buffer(1); -- lights(0) <= not compass_buffer(0); end case; end if; end process getadinfo; end behaviour;