From 2beb7f4b4d1c0a57448cb2992d7db8ca2dcb7217 Mon Sep 17 00:00:00 2001 From: Greek Date: Thu, 12 Mar 2020 20:20:35 +0100 Subject: [PATCH] * .gitignore update * Added implementation for PMOD-AD1 Controller including testbench * Added implementation for PMOD-DA3 Controller including testbench --- .gitignore | 8 ++- modelsim/pmod-ad1.do | 28 +++++++++ modelsim/pmod-da3.do | 30 ++++++++++ src/pmod_ad1_ctrl.vhd | 123 +++++++++++++++++++++++++++++++++++++++ src/pmod_ad1_ctrl_tb.vhd | 74 +++++++++++++++++++++++ src/pmod_da3_ctrl.vhd | 109 ++++++++++++++++++++++++++++++++++ src/pmod_da3_ctrl_tb.vhd | 77 ++++++++++++++++++++++++ 7 files changed, 447 insertions(+), 2 deletions(-) create mode 100644 modelsim/pmod-ad1.do create mode 100644 modelsim/pmod-da3.do create mode 100644 src/pmod_ad1_ctrl.vhd create mode 100644 src/pmod_ad1_ctrl_tb.vhd create mode 100644 src/pmod_da3_ctrl.vhd create mode 100644 src/pmod_da3_ctrl_tb.vhd diff --git a/.gitignore b/.gitignore index 80e9d6e..eba538a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ -#Ignore complete Vivado Directory +#Ignore List /syn/** +/modelsim/** + #Unignore Directories (Needed to unignore files in Subdirectories) !*/ #WHITELIST #Vivado Project File -!*.xpr \ No newline at end of file +!*.xpr +#Modelsim Do files +!*.do \ No newline at end of file diff --git a/modelsim/pmod-ad1.do b/modelsim/pmod-ad1.do new file mode 100644 index 0000000..311d1e2 --- /dev/null +++ b/modelsim/pmod-ad1.do @@ -0,0 +1,28 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +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/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 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ps +update +WaveRestoreZoom {0 ps} {507648 ps} diff --git a/modelsim/pmod-da3.do b/modelsim/pmod-da3.do new file mode 100644 index 0000000..37277fd --- /dev/null +++ b/modelsim/pmod-da3.do @@ -0,0 +1,30 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate /pmod_da3_ctrl_tb/clk +add wave -noupdate /pmod_da3_ctrl_tb/reset +add wave -noupdate /pmod_da3_ctrl_tb/cs_n +add wave -noupdate /pmod_da3_ctrl_tb/start +add wave -noupdate /pmod_da3_ctrl_tb/done +add wave -noupdate /pmod_da3_ctrl_tb/sdata +add wave -noupdate /pmod_da3_ctrl_tb/ldac +add wave -noupdate /pmod_da3_ctrl_tb/data +add wave -noupdate /pmod_da3_ctrl_tb/uut/stage +add wave -noupdate /pmod_da3_ctrl_tb/uut/count +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {70507 ps} 0} +quietly wave cursor active 1 +configure wave -namecolwidth 150 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +configure wave -timelineunits ps +update +WaveRestoreZoom {0 ps} {961024 ps} diff --git a/src/pmod_ad1_ctrl.vhd b/src/pmod_ad1_ctrl.vhd new file mode 100644 index 0000000..3d1ff21 --- /dev/null +++ b/src/pmod_ad1_ctrl.vhd @@ -0,0 +1,123 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Controller for the PMOD AD1 Digilent Board. +-- The controller keeps the AD7476A in "normal mode" throughout its operation, and as long as the enable +-- signal is high, converts the ADC input signal at a rate of sclk_freq/(TRANSFER_CLK_COUNT+DELAY_CLK_CNT). +-- On conversion finish the done signal is pulsed high for a sclk cycle. The data outputs contain valid +-- data only when done is asserted. If enable is pulled low, the controller enters a standby mode and +-- waits until the enable signal is pulled high again. If the enable is pulled low during a +-- converion/transfer, the conversion/transfer is completed before entering the idle mode. + +entity pmod_ad1_ctrl is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DELAY_CLK_CNT : integer := 2; + DATA_BITS : integer := 12 + ); + port ( + sclk : in std_logic; -- PMOD-AD1 + reset : in std_logic; + sdata1 : in std_logic; -- PMOD-AD1 + 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); + done : out std_logic + ); +end entity; + +architecture arch of pmod_ad1_ctrl is + + --*****TYPE DECLARATION***** + type STAGE_TYPE is (IDLE, TRANSFER, DELAY); + + --*****SIGNAL DECLARATIONS***** + signal buf1, buf2, buf1_next, buf2_next : std_logic_vector(DATA_BITS-1 downto 0) := (others => '0'); + signal stage, stage_next : STAGE_TYPE := IDLE; + signal count, count_next : integer range 0 to 16 := 0; + -- Output Signals + signal cs_n_next : std_logic := '1'; + signal done_next : std_logic := '0'; + +begin + + state : process(all) + begin + -- DEFAULT VALUES + buf1_next <= buf1; + buf2_next <= buf2; + stage_next <= stage; + count_next <= count; + done_next <= '0'; + cs_n_next <= '1'; + + case stage is + when IDLE => + if (enable = '1') then + stage_next <= TRANSFER; + cs_n_next <= '0'; + count_next <= 1; + end if; + -- NOTE: This state remains longer than the width of the data word. This is by design + -- to shift out the initial zero bits of the tranfer. + when TRANSFER => + -- Shift Bits into buffer + buf1_next <= buf1(DATA_BITS-2 downto 0) & sdata1; + buf2_next <= buf2(DATA_BITS-2 downto 0) & sdata2; + cs_n_next <= '0'; + if (count = TRANSFER_CLK_COUNT) then + stage_next <= DELAY; + count_next <= 1; + cs_n_next <= '1'; + done_next <= '1'; + else + count_next <= count + 1; + end if; + when DELAY => + if (count = DELAY_CLK_CNT) then + if(enable = '1') then + stage_next <= TRANSFER; + cs_n_next <= '0'; + count_next <= 1; + else + stage_next <= IDLE; + end if; + else + count_next <= count + 1; + end if; + end case; + end process; + + sync : process(sclk) + begin + if (rising_edge(sclk)) then + if (reset = '1') then + -- Internal Signals + buf1 <= (others => '0'); + buf2 <= (others => '0'); + stage <= IDLE; + count <= 0; + -- Output Signals + cs_n <= '1'; + data1 <= (others => '0'); + data2 <= (others => '0'); + done <= '0'; + else + -- Internal Signals + buf1 <= buf1_next; + buf2 <= buf2_next; + stage <= stage_next; + count <= count_next; + -- Output Signals + cs_n <= cs_n_next; + data1 <= buf1_next; + data2 <= buf2_next; + done <= done_next; + end if; + end if; + end process; + +end architecture; diff --git a/src/pmod_ad1_ctrl_tb.vhd b/src/pmod_ad1_ctrl_tb.vhd new file mode 100644 index 0000000..9d8de4a --- /dev/null +++ b/src/pmod_ad1_ctrl_tb.vhd @@ -0,0 +1,74 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity pmod_ad1_ctrl_tb is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DELAY_CLK_CNT : integer := 2; + DATA_BITS : integer := 12 + ); +end entity; + +architecture beh of pmod_ad1_ctrl_tb is + + --*****COMPONENT DECLARATION***** + component pmod_ad1_ctrl is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DELAY_CLK_CNT : integer := 2; + DATA_BITS : integer := 12 + ); + port ( + sclk : in std_logic; -- PMOD-AD1 + reset : in std_logic; + sdata1 : in std_logic; -- PMOD-AD1 + 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); + 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); + +begin + + uut : pmod_ad1_ctrl + generic map( + TRANSFER_CLK_COUNT => TRANSFER_CLK_COUNT, + DELAY_CLK_CNT => DELAY_CLK_CNT, + DATA_BITS => DATA_BITS + ) + port map( + sclk => clk, + reset => reset, + sdata1 => '1', + sdata2 => '1', + enable => '1', + cs_n => cs_n, + data1 => data1, + data2 => data2, + done => done + ); + + clk_prc : process + begin + clk <= '1'; + wait for 25 ns; + clk <= '0'; + wait for 25 ns; + end process; + + process + begin + --INITIALISE SIGNALS + reset <= '0'; + wait; + end process; + +end architecture; diff --git a/src/pmod_da3_ctrl.vhd b/src/pmod_da3_ctrl.vhd new file mode 100644 index 0000000..986572b --- /dev/null +++ b/src/pmod_da3_ctrl.vhd @@ -0,0 +1,109 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Controller for the PMOD DA3 Digilent Board. +-- The controller sends the input 'data' word to the DAC when 'start' is asserted. The 'data' input has +-- to be valid only during the period 'start' is asserted, as for the transfer the word is latched +-- internally. When the transfer is done, the 'done' signal is asserted for one clock cycle. The 'start' +-- and 'done' cycle can be high at the same time, allowing the done signal to be asynchronously connected +-- to the 'start' signal to save on latency. + + +entity pmod_da3_ctrl is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DATA_BITS : integer := 16 + ); + port ( + sclk : in std_logic; -- PMOD-DA3 + reset : in std_logic; + start : in std_logic; + data : in std_logic_vector(DATA_BITS-1 downto 0); + cs_n : out std_logic;-- PMOD-DA3 + sdata : out std_logic;-- PMOD-DA3 + ldac : out std_logic;-- PMOD-DA3 + done : out std_logic + ); +end entity; + +architecture arch of pmod_da3_ctrl is + + --*****TYPE DECLARATION***** + type STAGE_TYPE is (IDLE, TRANSFER); + + --*****SIGNAL DECLARATIONS***** + signal buf, buf_next : std_logic_vector(DATA_BITS-1 downto 0) := (others => '0'); + signal stage, stage_next : STAGE_TYPE := IDLE; + signal count, count_next : integer range 0 to 16 := 0; + -- Output Signals + signal cs_n_next : std_logic := '1'; + signal sdata_next : std_logic := '0'; + signal done_next : std_logic := '0'; + +begin + + --LDAC Hardwired to ground + ldac <= '0'; + + state : process(all) + begin + -- DEFAULT VALUES + buf_next <= buf; + stage_next <= stage; + count_next <= count; + done_next <= '0'; + cs_n_next <= '1'; + sdata_next <= '0'; + + case stage is + when IDLE => + if (start = '1') then + stage_next <= TRANSFER; + cs_n_next <= '0'; + count_next <= 1; + -- Shift first bit into DAC + buf_next <= data(DATA_BITS-2 downto 0) & '0'; + sdata_next <= data(DATA_BITS-1); + end if; + when TRANSFER => + -- Shift Bits into DAC + buf_next <= buf(DATA_BITS-2 downto 0) & '0'; + sdata_next <= buf(DATA_BITS-1); + cs_n_next <= '0'; + if (count = TRANSFER_CLK_COUNT) then + cs_n_next <= '1'; + stage_next <= IDLE; + done_next <= '1'; + else + count_next <= count + 1; + end if; + end case; + end process; + + sync : process(sclk) + begin + if (rising_edge(sclk)) then + if (reset = '1') then + -- Internal Signals + buf <= (others => '0'); + stage <= IDLE; + count <= 0; + -- Output Signals + cs_n <= '1'; + sdata <= '0'; + done <= '0'; + else + -- Internal Signals + buf <= buf_next; + stage <= stage_next; + count <= count_next; + -- Output Signals + cs_n <= cs_n_next; + sdata <= sdata_next; + done <= done_next; + end if; + end if; + end process; + +end architecture; diff --git a/src/pmod_da3_ctrl_tb.vhd b/src/pmod_da3_ctrl_tb.vhd new file mode 100644 index 0000000..c296624 --- /dev/null +++ b/src/pmod_da3_ctrl_tb.vhd @@ -0,0 +1,77 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity pmod_da3_ctrl_tb is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DATA_BITS : integer := 16 + ); +end entity; + +architecture beh of pmod_da3_ctrl_tb is + + --*****COMPONENT DECLARATION***** + component pmod_da3_ctrl is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DATA_BITS : integer := 16 + ); + port ( + sclk : in std_logic; -- PMOD-DA3 + reset : in std_logic; + start : in std_logic; + data : in std_logic_vector(DATA_BITS-1 downto 0); + cs_n : out std_logic;-- PMOD-DA3 + sdata : out std_logic;-- PMOD-DA3 + ldac : out std_logic;-- PMOD-DA3 + done : out std_logic + ); + end component; + + --*****SIGNAL DEFINITIONS***** + signal clk, reset, cs_n, start, done, sdata, ldac : std_logic := '0'; + signal data : std_logic_vector(DATA_BITS-1 downto 0) := (others => '0'); + +begin + + uut : pmod_da3_ctrl + generic map( + TRANSFER_CLK_COUNT => TRANSFER_CLK_COUNT, + DATA_BITS => DATA_BITS + ) + port map( + sclk => clk, + reset => reset, + start => start, + data => data, + cs_n => cs_n, + sdata => sdata, + ldac => ldac, + done => done + ); + + clk_prc : process + begin + clk <= '1'; + wait for 25 ns; + clk <= '0'; + wait for 25 ns; + end process; + + process + begin + --INITIALISE SIGNALS + reset <= '0'; + wait for 5 ns; + wait until rising_edge(clk); + start <= '1'; + data <= (others => '1'); + wait until rising_edge(clk); + start <= '0'; + data <= (others => '0'); + wait until rising_edge(done); + wait; + end process; + +end architecture;