diff --git a/modelsim/pmod-ad1.do b/modelsim/pmod-ad1.do index 311d1e2..8dcca6d 100644 --- a/modelsim/pmod-ad1.do +++ b/modelsim/pmod-ad1.do @@ -4,13 +4,13 @@ add wave -noupdate /pmod_ad1_ctrl_tb/clk add wave -noupdate /pmod_ad1_ctrl_tb/reset add wave -noupdate /pmod_ad1_ctrl_tb/cs_n add wave -noupdate /pmod_ad1_ctrl_tb/done +add wave -noupdate /pmod_ad1_ctrl_tb/sdata1 add wave -noupdate /pmod_ad1_ctrl_tb/data1 -add wave -noupdate /pmod_ad1_ctrl_tb/data2 add wave -noupdate /pmod_ad1_ctrl_tb/uut/stage add wave -noupdate /pmod_ad1_ctrl_tb/uut/count TreeUpdate [SetDefaultTree] -WaveRestoreCursors {{Cursor 1} {0 ps} 0} -quietly wave cursor active 0 +WaveRestoreCursors {{Cursor 1} {99527 ps} 0} +quietly wave cursor active 1 configure wave -namecolwidth 150 configure wave -valuecolwidth 100 configure wave -justifyvalue left @@ -25,4 +25,4 @@ configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ps update -WaveRestoreZoom {0 ps} {507648 ps} +WaveRestoreZoom {0 ps} {1015296 ps} diff --git a/src/PMOD_AD1.vhd b/src/PMOD_AD1.vhd new file mode 100644 index 0000000..5520b38 --- /dev/null +++ b/src/PMOD_AD1.vhd @@ -0,0 +1,269 @@ +------------------------------------------------------------------------- +-- AD1_controller.VHD +------------------------------------------------------------------------- +-- Author : Todd Harless +-- CopyRight 2005 Digilent, Inc. +------------------------------------------------------------------------- +-- Description : This file is the VHDL code for a PMOD-AD1 controller. +-- +------------------------------------------------------------------------- +-- Revision History: +-- 07/11/2005 Created (Todd Harless) +-- 08/09/2005 revision 0.1 (Todd Harless) +------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + + + +------------------------------------------------------------------------- +--Title : AD1 controller entity +-- +-- Inputs : 3 +-- Outputs : 3 +-- +-- Description : This is the AD1 controller entity. The input ports are +-- a 50 MHz clock and an asynchronous +-- reset button along with the data from the ADC7476 that +-- is serially shifted in on each clock cycle. The outputs +-- are the SCLK signal which clocks the PMOD-AD1 board at +-- 12.5 MHz and a chip select signal (CS) that latches the +-- data into the PMOD-AD1 board as well as an 12-bit output +-- vector labeled DATA_OUT which can be used by any +-- external components. +-- +-------------------------------------------------------------------------- + + +entity AD1_controller is + Port ( + --General usage + CLK : in std_logic; -- System Clock (50MHz) + RST : in std_logic; + + --Pmod interface signals + SDATA1 : in std_logic; + SDATA2 : in std_logic; + SCLK : out std_logic; + CS : out std_logic; + + --User interface signals + DATA1 : out std_logic_vector(11 downto 0); + DATA2 : out std_logic_vector(11 downto 0); + START : in std_logic; + DONE : out std_logic + + + ); +end AD1_controller; + +architecture AD1 of AD1_controller is + +-------------------------------------------------------------------------------- +--Title : Local signal assignments +-- +-- Description : The following signals will be used to drive the processes of +-- this VHDL file. +-- +-- current_state: This signal will be the pointer that will point at the +-- current state of the Finite State Machine of the +-- controller. +-- next_state : This signal will be the pointer that will point at the +-- current state of the Finite State Machine of the +-- controller. +-- temp1 : This is a 16-bit vector that will store the 16-bits of data +-- that are serially shifted-in form the first ADC7476 chip inside the +-- PMOD-AD1 board. +-- temp2 : This is a 16-bit vector that will store the 16-bits of data +-- that are serially shifted-in form the second ADC7476 chip inside the +-- PMOD-AD1 board. +-- dat1 : This is a 12-bit vector that will store the 12-bits of actual data +-- that are serially shifted-in form the first ADC7476 chip inside the +-- PMOD-AD1 board. +-- dat2 : This is a 12-bit vector that will store the 12-bits of actual data +-- that are serially shifted-in form the second ADC7476 chip inside the +-- PMOD-AD1 board. +-- clk_div : This will be the divided 12.5 MHz clock signal that will +-- clock the PMOD-AD1 board +-- clk_counter : This counter will be used to create a divided clock signal. +-- +-- shiftCounter : This counter will be used to count the shifted data from the +-- ADC7476 chip inside the PMOD-AD1 board. +-- enShiftCounter : This signal will be used to enable the counter for the shifted +-- data from the ADC7476 chip inside the PMOD-AD1 board. +-- enParalelLoad : This signal will be used to enable the load in a register the shifted +-- data. +-------------------------------------------------------------------------------- + +type states is (Idle, + ShiftIn, + SyncData); + signal current_state : states; + signal next_state : states; + + signal temp1 : std_logic_vector(15 downto 0) := (others => '0'); + signal temp2 : std_logic_vector(15 downto 0) := (others => '0'); + signal dat1 : std_logic_vector(11 downto 0):= x"000"; + signal dat2 : std_logic_vector(11 downto 0):= x"000"; + signal clk_div : std_logic; + signal clk_counter : std_logic_vector(27 downto 0); + signal shiftCounter : std_logic_vector(3 downto 0) := x"0"; + signal enShiftCounter: std_logic; + signal enParalelLoad : std_logic; + + + +begin + + + +-------------------------------------------------------------------------------- +--Title : clock divider process +-- +-- Description : This is the process that will divide the 50 MHz clock +-- down to a clock speed of 12.5 MHz to drive the ADC7476 chip. +-------------------------------------------------------------------------------- + clock_divide : process(rst,clk) + begin + if rst = '1' then + clk_counter <= "0000000000000000000000000000"; + elsif (clk = '1' and clk'event) then + clk_counter <= clk_counter + '1'; + end if; + end process; + + clk_div <= clk_counter(1); + SCLK <= not clk_counter(1); + +----------------------------------------------------------------------------------- +-- +-- Title : counter +-- +-- Description: This is the process were the teporary registers will be loaded and +-- shifted.When the enParalelLoad signal is generated inside the state +-- the temp1 and temp2 registers will be loaded with the 8 bits of control +-- concatenated with the 8 bits of data. When the enShiftCounter is +-- activated, the 16-bits of data inside the temporary registers will be +-- shifted. A 4-bit counter is used to keep shifting the data +-- inside temp1 and temp2 for 16 clock cycles. +-- +----------------------------------------------------------------------------------- + +counter : process(clk_div, enParalelLoad, enShiftCounter) + begin + if (clk_div = '1' and clk_div'event) then + + if (enShiftCounter = '1') then + temp1 <= temp1(14 downto 0) & SDATA1; + temp2 <= temp2(14 downto 0) & SDATA2; + shiftCounter <= shiftCounter + '1'; + elsif (enParalelLoad = '1') then + shiftCounter <= "0000"; + dat1 <= temp1(11 downto 0); + dat2 <= temp2(11 downto 0); + end if; + end if; + end process; + DATA1 <= dat1 ; + DATA2 <= dat2 ; +--------------------------------------------------------------------------------- +-- +-- Title : Finite State Machine +-- +-- Description: This 3 processes represent the FSM that contains three states. The first +-- state is the Idle state in which a temporary registers are +-- assigned the updated value of the input "DATA1" and "DATA2". The next state +-- is the ShiftIn state where the 16-bits of +-- data from each of the ADCS7476 chips are left shifted in the temp1 and temp2 shift registers. +-- The third +-- state SyncData drives the output signal CS high for +-- 1 clock period, and the second one in the Idle state telling the ADCS7476 to mark the end of the conversion. +-- Notes: The data will change on the lower edge of the clock signal. Their +-- is also an asynchronous reset that will reset all signals to their +-- original state. +-- +----------------------------------------------------------------------------------- + +----------------------------------------------------------------------------------- +-- +-- Title : SYNC_PROC +-- +-- Description: This is the process were the states are changed synchronously. At +-- reset the current state becomes Idle state. +-- +----------------------------------------------------------------------------------- +SYNC_PROC: process (clk_div, rst) + begin + if (clk_div'event and clk_div = '1') then + if (rst = '1') then + current_state <= Idle; + else + current_state <= next_state; + end if; + end if; + end process; + +----------------------------------------------------------------------------------- +-- +-- Title : OUTPUT_DECODE +-- +-- Description: This is the process were the output signals are generated +-- unsynchronously based on the state only (Moore State Machine). +-- +----------------------------------------------------------------------------------- +OUTPUT_DECODE: process (current_state) + begin + if current_state = Idle then + enShiftCounter <='0'; + DONE <='1'; + CS <='1'; + enParalelLoad <= '0'; + elsif current_state = ShiftIn then + enShiftCounter <='1'; + DONE <='0'; + CS <='0'; + enParalelLoad <= '0'; + else --if current_state = SyncData then + enShiftCounter <='0'; + DONE <='0'; + CS <='1'; + enParalelLoad <= '1'; + end if; + end process; + +---------------------------------------------------------------------------------- +-- +-- Title : NEXT_STATE_DECODE +-- +-- Description: This is the process were the next state logic is generated +-- depending on the current state and the input signals. +-- +----------------------------------------------------------------------------------- + NEXT_STATE_DECODE: process (current_state, START, shiftCounter) + begin + + next_state <= current_state; --default is to stay in current state + + case (current_state) is + when Idle => + if START = '1' then + next_state <= ShiftIn; + end if; + when ShiftIn => + if shiftCounter = x"F" then + next_state <= SyncData; + end if; + when SyncData => + if START = '0' then + next_state <= Idle; + end if; + when others => + next_state <= Idle; + end case; + end process; + + +end AD1; diff --git a/src/sim/pmod_ad1_ctrl_tb.vhd b/src/sim/pmod_ad1_ctrl_tb.vhd index 9d8de4a..620b350 100644 --- a/src/sim/pmod_ad1_ctrl_tb.vhd +++ b/src/sim/pmod_ad1_ctrl_tb.vhd @@ -6,7 +6,7 @@ entity pmod_ad1_ctrl_tb is generic( TRANSFER_CLK_COUNT : integer := 16; DELAY_CLK_CNT : integer := 2; - DATA_BITS : integer := 12 + DATA_WIDTH : integer := 12 ); end entity; @@ -17,7 +17,7 @@ architecture beh of pmod_ad1_ctrl_tb is generic( TRANSFER_CLK_COUNT : integer := 16; DELAY_CLK_CNT : integer := 2; - DATA_BITS : integer := 12 + DATA_WIDTH : integer := 12 ); port ( sclk : in std_logic; -- PMOD-AD1 @@ -26,15 +26,15 @@ architecture beh of pmod_ad1_ctrl_tb is sdata2 : in std_logic; -- PMOD-AD1 enable : in std_logic; cs_n : out std_logic;-- PMOD-AD1 - data1 : out std_logic_vector(DATA_BITS-1 downto 0); - data2 : out std_logic_vector(DATA_BITS-1 downto 0); + data1 : out std_logic_vector(DATA_WIDTH-1 downto 0); + data2 : out std_logic_vector(DATA_WIDTH-1 downto 0); done : out std_logic ); end component; --*****SIGNAL DEFINITIONS***** - signal clk, reset, cs_n, done : std_logic := '0'; - signal data1, data2 : std_logic_vector(DATA_BITS-1 downto 0); + signal clk, reset, cs_n, done, sdata1, sdata2 : std_logic := '0'; + signal data1, data2 : std_logic_vector(DATA_WIDTH-1 downto 0); begin @@ -42,13 +42,13 @@ begin generic map( TRANSFER_CLK_COUNT => TRANSFER_CLK_COUNT, DELAY_CLK_CNT => DELAY_CLK_CNT, - DATA_BITS => DATA_BITS + DATA_WIDTH => DATA_WIDTH ) port map( sclk => clk, reset => reset, - sdata1 => '1', - sdata2 => '1', + sdata1 => sdata1, + sdata2 => sdata2, enable => '1', cs_n => cs_n, data1 => data1, @@ -64,9 +64,19 @@ begin wait for 25 ns; end process; + data_prc : process + begin + wait until rising_edge(clk); + sdata1 <= not sdata1; + sdata2 <= not sdata2; + end process; + process begin --INITIALISE SIGNALS + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); reset <= '0'; wait; end process; diff --git a/src/sim/pmod_ad1_tb.vhd b/src/sim/pmod_ad1_tb.vhd new file mode 100644 index 0000000..24ad01d --- /dev/null +++ b/src/sim/pmod_ad1_tb.vhd @@ -0,0 +1,78 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity pmod_ad1_tb is +end entity; + +architecture beh of pmod_ad1_tb is + + --*****COMPONENT DECLARATION***** + component AD1_controller is + port ( + --General usage + CLK : in std_logic; -- System Clock (50MHz) + RST : in std_logic; + --Pmod interface signals + SDATA1 : in std_logic; + SDATA2 : in std_logic; + SCLK : out std_logic; + CS : out std_logic; + --User interface signals + DATA1 : out std_logic_vector(11 downto 0); + DATA2 : out std_logic_vector(11 downto 0); + START : in std_logic; + DONE : out std_logic + ); + end component; + + --*****SIGNAL DEFINITIONS***** + signal clk, reset, cs_n, done, sclk : std_logic := '0'; + signal sdata1, sdata2 : std_logic := '0'; + signal data1, data2 : std_logic_vector(11 downto 0); + +begin + + uut : AD1_controller + port map ( + --General usage + CLK => clk, + RST => reset, + --Pmod interface signals + SDATA1 => sdata1, + SDATA2 => sdata2, + SCLK => sclk, + CS => cs_n, + --User interface signals + DATA1 => data1, + DATA2 => data2, + START => done, + DONE => done + ); + + clk_prc : process + begin + clk <= '1'; + wait for 25 ns; + clk <= '0'; + wait for 25 ns; + end process; + + data_prc : process + begin + wait until falling_edge(sclk); + sdata1 <= not sdata1; + sdata2 <= not sdata2; + end process; + + process + begin + --INITIALISE SIGNALS + reset <= '1'; + wait until rising_edge(clk); + wait until rising_edge(clk); + reset <= '0'; + wait; + end process; + +end architecture;