* Modify PMOD-AS1 testbench

* Add reference PMOD AD1 controller
	- Including testbench
This commit is contained in:
Greek 2020-04-29 13:28:41 +02:00
parent ae928c116b
commit 131a9b3a6e
4 changed files with 370 additions and 13 deletions

View File

@ -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/reset
add wave -noupdate /pmod_ad1_ctrl_tb/cs_n add wave -noupdate /pmod_ad1_ctrl_tb/cs_n
add wave -noupdate /pmod_ad1_ctrl_tb/done 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/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/stage
add wave -noupdate /pmod_ad1_ctrl_tb/uut/count add wave -noupdate /pmod_ad1_ctrl_tb/uut/count
TreeUpdate [SetDefaultTree] TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {0 ps} 0} WaveRestoreCursors {{Cursor 1} {99527 ps} 0}
quietly wave cursor active 0 quietly wave cursor active 1
configure wave -namecolwidth 150 configure wave -namecolwidth 150
configure wave -valuecolwidth 100 configure wave -valuecolwidth 100
configure wave -justifyvalue left configure wave -justifyvalue left
@ -25,4 +25,4 @@ configure wave -griddelta 40
configure wave -timeline 0 configure wave -timeline 0
configure wave -timelineunits ps configure wave -timelineunits ps
update update
WaveRestoreZoom {0 ps} {507648 ps} WaveRestoreZoom {0 ps} {1015296 ps}

269
src/PMOD_AD1.vhd Normal file
View File

@ -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;

View File

@ -6,7 +6,7 @@ entity pmod_ad1_ctrl_tb is
generic( generic(
TRANSFER_CLK_COUNT : integer := 16; TRANSFER_CLK_COUNT : integer := 16;
DELAY_CLK_CNT : integer := 2; DELAY_CLK_CNT : integer := 2;
DATA_BITS : integer := 12 DATA_WIDTH : integer := 12
); );
end entity; end entity;
@ -17,7 +17,7 @@ architecture beh of pmod_ad1_ctrl_tb is
generic( generic(
TRANSFER_CLK_COUNT : integer := 16; TRANSFER_CLK_COUNT : integer := 16;
DELAY_CLK_CNT : integer := 2; DELAY_CLK_CNT : integer := 2;
DATA_BITS : integer := 12 DATA_WIDTH : integer := 12
); );
port ( port (
sclk : in std_logic; -- PMOD-AD1 sclk : in std_logic; -- PMOD-AD1
@ -26,15 +26,15 @@ architecture beh of pmod_ad1_ctrl_tb is
sdata2 : in std_logic; -- PMOD-AD1 sdata2 : in std_logic; -- PMOD-AD1
enable : in std_logic; enable : in std_logic;
cs_n : out std_logic;-- PMOD-AD1 cs_n : out std_logic;-- PMOD-AD1
data1 : 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_BITS-1 downto 0); data2 : out std_logic_vector(DATA_WIDTH-1 downto 0);
done : out std_logic done : out std_logic
); );
end component; end component;
--*****SIGNAL DEFINITIONS***** --*****SIGNAL DEFINITIONS*****
signal clk, reset, cs_n, done : std_logic := '0'; signal clk, reset, cs_n, done, sdata1, sdata2 : std_logic := '0';
signal data1, data2 : std_logic_vector(DATA_BITS-1 downto 0); signal data1, data2 : std_logic_vector(DATA_WIDTH-1 downto 0);
begin begin
@ -42,13 +42,13 @@ begin
generic map( generic map(
TRANSFER_CLK_COUNT => TRANSFER_CLK_COUNT, TRANSFER_CLK_COUNT => TRANSFER_CLK_COUNT,
DELAY_CLK_CNT => DELAY_CLK_CNT, DELAY_CLK_CNT => DELAY_CLK_CNT,
DATA_BITS => DATA_BITS DATA_WIDTH => DATA_WIDTH
) )
port map( port map(
sclk => clk, sclk => clk,
reset => reset, reset => reset,
sdata1 => '1', sdata1 => sdata1,
sdata2 => '1', sdata2 => sdata2,
enable => '1', enable => '1',
cs_n => cs_n, cs_n => cs_n,
data1 => data1, data1 => data1,
@ -64,9 +64,19 @@ begin
wait for 25 ns; wait for 25 ns;
end process; end process;
data_prc : process
begin
wait until rising_edge(clk);
sdata1 <= not sdata1;
sdata2 <= not sdata2;
end process;
process process
begin begin
--INITIALISE SIGNALS --INITIALISE SIGNALS
reset <= '1';
wait until rising_edge(clk);
wait until rising_edge(clk);
reset <= '0'; reset <= '0';
wait; wait;
end process; end process;

78
src/sim/pmod_ad1_tb.vhd Normal file
View File

@ -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;