--------------------------------------------------------------------------------- -- Digital RF Telemetry Project -- -- file: tempadc.vhd -- by Alex Tong -- Nov 25, 1999 -- -- purpose: to latch data from the temperature Analog-to-Digital -- converter and display the info to a 7 segment LED -- -- adc1_buffer(0) = MSB of actual data stream -- adc1_buffer(1) = Next data bit of actual data stream -- adc1_buffer(5) = LSB 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 tempadc is port ( clock : in std_logic; pb1 : in std_logic; cs : out std_logic; -- dclock is used for modular testing only -- dclock : out std_logic; adc1 : in std_logic; adc1_buffer : buffer std_logic_vector(5 downto 0); led2 : out std_logic_vector(7 downto 0) ); end entity tempadc; architecture behaviour of tempadc 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; -- timer signals and timer control signals signal timer_reset1, timer_start1, timer_running1, timer_running2 : std_logic; signal restart_timer : std_logic; signal delaystate : std_logic_vector(3 downto 0); signal latchdata : std_logic; -- lpm counter signals --signal count_en1, internal_reset : std_logic; signal count : std_logic_vector(7 downto 0); -- unconnected/unused ports signal nowhere1, nowhere2 : std_logic; -- dclock is only used in modular testing --signal dclock : std_logic; -- pb1 debounced 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); signal bitcount : 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); -- data clocking is needed for modular testing only -- dclock is usually supplied by the top-level file -- 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 => nowhere1, -- 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; ---------------------------------------------------------- -- -- process to latch data at correct intervals from the ADC -- Two timers: -- timer1 controls when each data bit begins -- timer2 controls when to latch the data -- ---------------------------------------------------------- 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"; 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"; 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"; 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; latchdata <= '1'; else restart_timer <= '0'; end if; when "0011" => if pb1_deb = '1' then adc1_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; latchdata <= '1'; else restart_timer <= '0'; end if; when "0100" => if pb1_deb = '1' then adc1_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; latchdata <= '1'; else restart_timer <= '0'; end if; when "0101" => if pb1_deb = '1' then adc1_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; latchdata <= '1'; else restart_timer <= '0'; end if; when "0110" => if pb1_deb = '1' then adc1_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; latchdata <= '1'; else restart_timer <= '0'; end if; when "0111" => if pb1_deb = '1' then adc1_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; latchdata <= '1'; else restart_timer <= '0'; end if; when others => led2(0) <= not adc1_buffer(0); led2(1) <= not adc1_buffer(1); led2(2) <= not adc1_buffer(2); led2(3) <= not adc1_buffer(3); led2(4) <= not adc1_buffer(4); led2(5) <= not adc1_buffer(5); led2(6) <= '1'; led2(7) <= '1'; -- led2(8) <= '1'; -- led2(9) <= '1'; -- led2(10) <= '1'; -- led2(11) <= '1'; end case; end if; end process getadinfo; end behaviour;