diff --git a/PmodAD1 RefComp/AD1Refcomp.vhd b/PmodAD1 RefComp/AD1Refcomp.vhd new file mode 100644 index 0000000000000000000000000000000000000000..624ee760e089f2ad2a48e2517d8c9b7150591a29 --- /dev/null +++ b/PmodAD1 RefComp/AD1Refcomp.vhd @@ -0,0 +1,284 @@ +------------------------------------------------------------------------- +-- AD1RefComp.VHD +------------------------------------------------------------------------- +-- Author : Ioana Dabacan +-- CopyRight 2008 Digilent Ro. +------------------------------------------------------------------------- +-- Description : This file is the VHDL code for a PMOD-AD1 controller. +-- +------------------------------------------------------------------------- +-- Revision History: +-- Feb/29/2008 Created (Ioana Dabacan) +------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +package ADC is + component AD1RefComp is + Port ( + --General usage + CLK : in std_logic; + RST : in std_logic; + + --Pmod interface signals + SDATA1 : in std_logic; + SDATA2 : in std_logic; + SCLK : out std_logic; + nCS : 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 AD1RefComp; +end package ADC; + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +------------------------------------------------------------------------- +--Title : AD1 Reference Component +-- +-- Inputs : 5 +-- Outputs : 5 +-- +-- Description: This is the AD1 Reference Component 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(SDATA1 and +-- SDATA2). The outputs are the SCLK signal which clocks +-- the PMOD-AD1 board at 12.5 MHz and a chip select +-- signal (nCS) that enables the ADC7476 chips on the +-- PMOD-AD1 board as well as two 12-bit output +-- vectors labeled DATA1 and DATA2 which can be used by +-- any external components. The START is used to tell +-- the component when to start a conversion. After a +-- conversion is done the component activates the DONE +-- signal. +-- +-------------------------------------------------------------------------- + +entity AD1RefComp is + Port ( + --General usage + CLK : in std_logic; + RST : in std_logic; + + --Pmod interface signals + SDATA1 : in std_logic; + SDATA2 : in std_logic; + SCLK : out std_logic; + nCS : 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 AD1RefComp ; + +architecture AD1 of AD1RefComp 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. +-- 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. +-- enParalelLoad : This signal will be used to enable the load the shifted +-- data in a register. +-------------------------------------------------------------------------------- + +type states is (Idle, + ShiftIn, + SyncData); + signal current_state : states; + signal next_state : states; + + signal temp1 : std_logic_vector(15 downto 0); + signal temp2 : std_logic_vector(15 downto 0); + signal clk_div : std_logic; + signal clk_counter : std_logic_vector(1 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 <= "00"; + 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 converted data will be colected and +-- output.When the enShiftCounter is activated, the 16-bits of data +-- from the ADC7476 chips will be shifted inside the temporary +-- registers. A 4-bit counter is used to keep shifting the data +-- inside temp1 and temp2 for 16 clock cycles. When the enParalelLoad +-- signal is generated inside the SyncData state, the converted data +-- in the temporary shift registers will be placed on the outputs +-- DATA1 and DATA2. +-- +----------------------------------------------------------------------------------- + +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"; + DATA1 <= temp1(11 downto 0); + DATA2 <= temp2(11 downto 0); + end if; + end if; + end process; + +--------------------------------------------------------------------------------- +-- +-- 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 nCS high for 1 clock period maintainig nCS high +-- also 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. There +-- 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'; + nCS <='1'; + enParalelLoad <= '0'; + elsif current_state = ShiftIn then + enShiftCounter <='1'; + DONE <='0'; + nCS <='0'; + enParalelLoad <= '0'; + else --if current_state = SyncData then + enShiftCounter <='0'; + DONE <='0'; + nCS <='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; \ No newline at end of file diff --git a/PmodDA2 RefComp/PmodDA2RefComp.pdf b/PmodDA2 RefComp/PmodDA2RefComp.pdf new file mode 100644 index 0000000000000000000000000000000000000000..39d0aea32f05eb96d38c8e22681cab0108e0874b Binary files /dev/null and b/PmodDA2 RefComp/PmodDA2RefComp.pdf differ diff --git a/PmodDA2 RefComp/SourceFiles/DA2RefComp.vhd b/PmodDA2 RefComp/SourceFiles/DA2RefComp.vhd new file mode 100644 index 0000000000000000000000000000000000000000..62200f296d6a65b02d73456c542ab4b92ae41baa --- /dev/null +++ b/PmodDA2 RefComp/SourceFiles/DA2RefComp.vhd @@ -0,0 +1,287 @@ +-------------------------------------------------------------------------------- +-- DA2 Reference Component +-------------------------------------------------------------------------------- +-- Author : Ioana Dabacan +-- CopyRight 2008 Digilent Ro. +-------------------------------------------------------------------------------- +-- Desription : This file is the VHDL code for a PMOD-DA2 controller. +-- +-------------------------------------------------------------------------------- +-- Revision History: +-- Feb/29/2008 (Created) Ioana Dabacan +-------------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + + +-------------------------------------------------------------------------------- +-- +-- Title : DA1 controller entity +-- +-- Inputs : 5 +-- Outputs : 5 +-- +-- Description: This is the DA2 Reference Component entity. The input ports are +-- a 50MHz clock and and an asynchronous reset button along with the +-- data to be serially shifted in the 2 DAC121S101 chips on a DA2 +-- Pmod on each clock cycle.There is also a signal to start a +-- conversion. +-- The outputs of this entity are: a output clock signal, two serial +-- output signals D1 and D2, a sync signal to synchronize the data +-- in the DAC121S101 chip, a done signal to tell that the chip is +-- done converting the data and another set of data can be sent. +-- +--------------------------------------------------------------------------------- + +entity DA2RefComp is + Port ( + + + --General usage + CLK : in std_logic; -- System Clock (50MHz) + RST : in std_logic; + + --Pmod interface signals + D1 : out std_logic; + --D2 : out std_slogic; + CLK_OUT : out std_logic; + nSYNC : out std_logic; + + --User interface signal + DATA1 : in std_logic_vector(7 downto 0); + -- DATA2 : in std_logic_vector(11 downto 0); + --START : in std_logic; + DONE : buffer std_logic + + ); +end DA2RefComp ; + +architecture DA2 of DA2RefComp is + + +-- control constant: Normal Operation + constant control : std_logic_vector(3 downto 0) := "0000"; +------------------------------------------------------------------------------------ +-- Title : signal assignments +-- +-- Description: The following signals are enumerated signals for the +-- finite state machine,2 temporary vectors to be shifted out to the +-- DAC121S101 chips, a divided clock signal to drive the DAC121S101 chips, +-- a counter to divide the internal 50 MHz clock signal, +-- a 4-bit counter to be used to shift out the 16-bit register, +-- and 2 enable signals for the paralel load and shift of the +-- shift register. +-- +------------------------------------------------------------------------------------ + type states is (Idle, + ShiftOut, + 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 clk_div : std_logic := '0'; + signal clk_counter : std_logic_vector(27 downto 0) := (others => '0'); + signal shiftCounter : std_logic_vector(3 downto 0) := (others => '0'); + signal enShiftCounter: std_logic := '0'; + signal enParalelLoad : std_logic := '0'; + signal data_int : std_logic_vector(11 downto 0) := (others => '0'); + + signal START : std_logic := '1'; + + signal sweep_clk : std_logic := '0'; + signal sweep_ctr : std_logic_vector(11 downto 0) := (others => '0'); +begin + + + + + + + + + +------------------------------------------------------------------------------------ +-- +-- Title : Clock Divider +-- +-- Description: The following process takes a 50 MHz clock and divides it down to a +-- 25 MHz clock signal by assigning the signals clk_out and clk_div +-- to the 2nd bit of the clk_counter vector. clk_div is used by +-- the Finite State Machine and clk_out is used by the DAC121S101 chips. +-- +------------------------------------------------------------------------------------ + + clock_divide : process(rst,clk) + begin + if rising_edge(clk) then + if rst = '1' then + clk_counter <= "0000000000000000000000000000"; + else + clk_counter <= clk_counter + '1'; + end if; + + end if; + end process; + + clk_div <= clk_counter(1); + clk_out <= clk_counter(1); + sweep_clk <= clk_counter(6); + + + +process(sweep_clk) begin + if(rising_edge(sweep_clk)) then + if(unsigned(sweep_ctr) >= 4095) then + sweep_ctr <= (others => '0'); + else + sweep_ctr <= sweep_ctr + '1'; + end if; + end if; +end process; + +data_int <= sweep_ctr; + + + +----------------------------------------------------------------------------------- +-- +-- 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 temp 2 for 16 clock cycles. +-- +----------------------------------------------------------------------------------- + +--data_int(11 downto 4) <= DATA1; +--data_int(3 downto 0) <= "1111"; +counter : process(clk_div, enParalelLoad, enShiftCounter) + begin + if rising_edge(clk_div) then + if enParalelLoad = '1' then + shiftCounter <= "0000"; + temp1 <= control & data_int; + --temp2 <= control & DATA2; + elsif (enShiftCounter = '1') then + temp1 <= temp1(14 downto 0)&temp1(15); + temp2 <= temp2(14 downto 0)&temp2(15); + shiftCounter <= shiftCounter + '1'; + end if; + end if; + end process; + + D1 <= temp1(15); + --D2 <= temp2(15); + + +--------------------------------------------------------------------------------- +-- +-- Title : Finite State Machine +-- +-- Description: This 3 processes represent the FSM that contains three states. +-- First one is the Idle state in which the temporary registers are +-- assigned the updated value of the input "DATA1" and "DATA2". +-- The next state is the ShiftOut state which is the state where the +-- 16-bits of temporary registers are shifted out left from the MSB +-- to the two serial outputs, D1 and D2. Immediately following the +-- second state is the third state SyncData. This state drives the +-- output signal sync high for2 clock signals telling the DAC121S101 +-- to latch the 16-bit data it just recieved in the previous state. +-- Notes: The data will change on the upper 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 rising_edge(clk_div) 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'; + nSYNC <='1'; + enParalelLoad <= '1'; + elsif current_state = ShiftOut then + enShiftCounter <='1'; + DONE <='0'; + nSYNC <='0'; + enParalelLoad <= '0'; + else --if current_state = SyncData then + enShiftCounter <='0'; + DONE <='0'; + nSYNC <='1'; + enParalelLoad <= '0'; + 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, CLK) -- added clk + begin + + next_state <= current_state; --default is to stay in current state + + case (current_state) is + when Idle => + if START = '1' and DONE = '1' then + next_state <= ShiftOut; + end if; + when ShiftOut => + if shiftCounter = x"F" then + next_state <= SyncData; + end if; + when SyncData => + if START = '1' then -- was 0 + next_state <= Idle; + end if; + when others => + next_state <= Idle; + end case; + end process; + + +end DA2; + + diff --git a/PmodDA2 RefComp/SourceFiles/backup_dac_inner.vhd b/PmodDA2 RefComp/SourceFiles/backup_dac_inner.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c6c0779670f6c7f046a35af8edcac448b49a1a70 --- /dev/null +++ b/PmodDA2 RefComp/SourceFiles/backup_dac_inner.vhd @@ -0,0 +1,785 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +use ieee.numeric_std.all; + +entity DAC_controller_v1_0_S00_AXI is + generic ( + -- Users to add parameters here + + -- User parameters ends + -- Do not modify the parameters beyond this line + + -- Width of S_AXI data bus + C_S_AXI_DATA_WIDTH : integer := 32; + -- Width of S_AXI address bus + C_S_AXI_ADDR_WIDTH : integer := 6 + ); + port ( + -- Users to add ports here + + S_GCLK : in std_logic; + S_GRESET : in std_logic; + S_D1 : out std_logic; + S_D2 : out std_logic; + S_CLK_OUT : out std_logic; + S_NSYNC : out std_logic; + + S_DONE : out std_logic; + S_EXT_START : in std_logic; + + S_LEDS_OUT : out std_logic_vector(7 downto 0); + + -- User ports ends + -- Do not modify the ports beyond this line + + + + + + + + -- Global Clock Signal + S_AXI_ACLK : in std_logic; + -- Global Reset Signal. This Signal is Active LOW + S_AXI_ARESETN : in std_logic; + -- Write address (issued by master, acceped by Slave) + S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); + -- Write channel Protection type. This signal indicates the + -- privilege and security level of the transaction, and whether + -- the transaction is a data access or an instruction access. + S_AXI_AWPROT : in std_logic_vector(2 downto 0); + -- Write address valid. This signal indicates that the master signaling + -- valid write address and control information. + S_AXI_AWVALID : in std_logic; + -- Write address ready. This signal indicates that the slave is ready + -- to accept an address and associated control signals. + S_AXI_AWREADY : out std_logic; + -- Write data (issued by master, acceped by Slave) + S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + -- Write strobes. This signal indicates which byte lanes hold + -- valid data. There is one write strobe bit for each eight + -- bits of the write data bus. + S_AXI_WSTRB : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0); + -- Write valid. This signal indicates that valid write + -- data and strobes are available. + S_AXI_WVALID : in std_logic; + -- Write ready. This signal indicates that the slave + -- can accept the write data. + S_AXI_WREADY : out std_logic; + -- Write response. This signal indicates the status + -- of the write transaction. + S_AXI_BRESP : out std_logic_vector(1 downto 0); + -- Write response valid. This signal indicates that the channel + -- is signaling a valid write response. + S_AXI_BVALID : out std_logic; + -- Response ready. This signal indicates that the master + -- can accept a write response. + S_AXI_BREADY : in std_logic; + -- Read address (issued by master, acceped by Slave) + S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); + -- Protection type. This signal indicates the privilege + -- and security level of the transaction, and whether the + -- transaction is a data access or an instruction access. + S_AXI_ARPROT : in std_logic_vector(2 downto 0); + -- Read address valid. This signal indicates that the channel + -- is signaling valid read address and control information. + S_AXI_ARVALID : in std_logic; + -- Read address ready. This signal indicates that the slave is + -- ready to accept an address and associated control signals. + S_AXI_ARREADY : out std_logic; + -- Read data (issued by slave) + S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + -- Read response. This signal indicates the status of the + -- read transfer. + S_AXI_RRESP : out std_logic_vector(1 downto 0); + -- Read valid. This signal indicates that the channel is + -- signaling the required read data. + S_AXI_RVALID : out std_logic; + -- Read ready. This signal indicates that the master can + -- accept the read data and response information. + S_AXI_RREADY : in std_logic + ); +end DAC_controller_v1_0_S00_AXI; + +architecture arch_imp of DAC_controller_v1_0_S00_AXI is + + -- AXI4LITE signals + signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); + signal axi_awready : std_logic; + signal axi_wready : std_logic; + signal axi_bresp : std_logic_vector(1 downto 0); + signal axi_bvalid : std_logic; + signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0); + signal axi_arready : std_logic; + signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal axi_rresp : std_logic_vector(1 downto 0); + signal axi_rvalid : std_logic; + + -- Example-specific design signals + -- local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH + -- ADDR_LSB is used for addressing 32/64 bit registers/memories + -- ADDR_LSB = 2 for 32 bits (n downto 2) + -- ADDR_LSB = 3 for 64 bits (n downto 3) + constant ADDR_LSB : integer := (C_S_AXI_DATA_WIDTH/32)+ 1; + constant OPT_MEM_ADDR_BITS : integer := 3; + ------------------------------------------------ + ---- Signals for user logic register space example + + + + + +-- control constant: Normal Operation + constant control : std_logic_vector(3 downto 0) := "0000"; + ------------------------------------------------------------------------------------ +-- Title : signal assignments +-- +-- Description: The following signals are enumerated signals for the +-- finite state machine,2 temporary vectors to be shifted out to the +-- DAC121S101 chips, a divided clock signal to drive the DAC121S101 chips, +-- a counter to divide the internal 50 MHz clock signal, +-- a 4-bit counter to be used to shift out the 16-bit register, +-- and 2 enable signals for the paralel load and shift of the +-- shift register. +-- +------------------------------------------------------------------------------------ + type states is (Idle, + ShiftOut, + SyncData); + signal current_state : states; + signal next_state : states; + + signal temp1 : std_logic_vector(15 downto 0); + signal temp2 : std_logic_vector(15 downto 0); + signal clk_div : std_logic; + signal clk_counter : std_logic_vector(27 downto 0); + signal shiftCounter : std_logic_vector(3 downto 0); + signal enShiftCounter: std_logic; + signal enParalelLoad : std_logic; + + signal DATA1 :std_logic_vector(11 downto 0); + signal DATA2 :std_logic_vector(11 downto 0); + + signal START : std_logic; + + -------------------------------------------------- + ---- Number of Slave Registers 16 + signal slv_reg0 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg1 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg2 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg3 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg4 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg5 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg6 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg7 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg8 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg9 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg10 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg11 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg12 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg13 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg14 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg15 :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal slv_reg_rden : std_logic; + signal slv_reg_wren : std_logic; + signal reg_data_out :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0); + signal byte_index : integer; + signal aw_en : std_logic; + +begin + -- I/O Connections assignments + + S_AXI_AWREADY <= axi_awready; + S_AXI_WREADY <= axi_wready; + S_AXI_BRESP <= axi_bresp; + S_AXI_BVALID <= axi_bvalid; + S_AXI_ARREADY <= axi_arready; + S_AXI_RDATA <= axi_rdata; + S_AXI_RRESP <= axi_rresp; + S_AXI_RVALID <= axi_rvalid; + -- Implement axi_awready generation + -- axi_awready is asserted for one S_AXI_ACLK clock cycle when both + -- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is + -- de-asserted when reset is low. + + process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + axi_awready <= '0'; + aw_en <= '1'; + else + if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then + -- slave is ready to accept write address when + -- there is a valid write address and write data + -- on the write address and data bus. This design + -- expects no outstanding transactions. + axi_awready <= '1'; + aw_en <= '0'; + elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then + aw_en <= '1'; + axi_awready <= '0'; + else + axi_awready <= '0'; + end if; + end if; + end if; + end process; + + -- Implement axi_awaddr latching + -- This process is used to latch the address when both + -- S_AXI_AWVALID and S_AXI_WVALID are valid. + + process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + axi_awaddr <= (others => '0'); + else + if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and aw_en = '1') then + -- Write Address latching + axi_awaddr <= S_AXI_AWADDR; + end if; + end if; + end if; + end process; + + -- Implement axi_wready generation + -- axi_wready is asserted for one S_AXI_ACLK clock cycle when both + -- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is + -- de-asserted when reset is low. + + process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + axi_wready <= '0'; + else + if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1' and aw_en = '1') then + -- slave is ready to accept write data when + -- there is a valid write address and write data + -- on the write address and data bus. This design + -- expects no outstanding transactions. + axi_wready <= '1'; + else + axi_wready <= '0'; + end if; + end if; + end if; + end process; + + -- Implement memory mapped register select and write logic generation + -- The write data is accepted and written to memory mapped registers when + -- axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to + -- select byte enables of slave registers while writing. + -- These registers are cleared when reset (active low) is applied. + -- Slave register write enable is asserted when valid address and data are available + -- and the slave is ready to accept the write address and write data. + slv_reg_wren <= axi_wready and S_AXI_WVALID and axi_awready and S_AXI_AWVALID ; + + process (S_AXI_ACLK) + variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0); + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + slv_reg0 <= (others => '0'); + slv_reg1 <= (others => '0'); + slv_reg2 <= (others => '0'); + slv_reg3 <= (others => '0'); + slv_reg4 <= (others => '0'); + slv_reg5 <= (others => '0'); + slv_reg6 <= (others => '0'); + slv_reg7 <= (others => '0'); + slv_reg8 <= (others => '0'); + slv_reg9 <= (others => '0'); + --slv_reg10 <= (others => '0'); + slv_reg11 <= (others => '0'); + slv_reg12 <= (others => '0'); + slv_reg13 <= (others => '0'); + slv_reg14 <= (others => '0'); + slv_reg15 <= (others => '0'); + else + loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB); + if (slv_reg_wren = '1') then + case loc_addr is + when b"0000" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 0 + slv_reg0(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0001" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 1 + slv_reg1(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0010" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 2 + slv_reg2(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0011" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 3 + slv_reg3(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0100" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 4 + slv_reg4(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0101" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 5 + slv_reg5(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0110" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 6 + slv_reg6(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"0111" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 7 + slv_reg7(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1000" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 8 + slv_reg8(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1001" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 9 + slv_reg9(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1010" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 10 + -- slv_reg10(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1011" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 11 + slv_reg11(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1100" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 12 + slv_reg12(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1101" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 13 + slv_reg13(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1110" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 14 + slv_reg14(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when b"1111" => + for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop + if ( S_AXI_WSTRB(byte_index) = '1' ) then + -- Respective byte enables are asserted as per write strobes + -- slave registor 15 + slv_reg15(byte_index*8+7 downto byte_index*8) <= S_AXI_WDATA(byte_index*8+7 downto byte_index*8); + end if; + end loop; + when others => + slv_reg0 <= slv_reg0; + slv_reg1 <= slv_reg1; + slv_reg2 <= slv_reg2; + slv_reg3 <= slv_reg3; + slv_reg4 <= slv_reg4; + slv_reg5 <= slv_reg5; + slv_reg6 <= slv_reg6; + slv_reg7 <= slv_reg7; + slv_reg8 <= slv_reg8; + slv_reg9 <= slv_reg9; + --slv_reg10 <= slv_reg10; + slv_reg11 <= slv_reg11; + slv_reg12 <= slv_reg12; + slv_reg13 <= slv_reg13; + slv_reg14 <= slv_reg14; + slv_reg15 <= slv_reg15; + end case; + end if; + end if; + end if; + end process; + + + + + + + +------------------------------------------------------------------------------------ +-- +-- Title : Clock Divider +-- +-- Description: The following process takes a 50 MHz clock and divides it down to a +-- 25 MHz clock signal by assigning the signals clk_out and clk_div +-- to the 2nd bit of the clk_counter vector. clk_div is used by +-- the Finite State Machine and clk_out is used by the DAC121S101 chips. +-- +------------------------------------------------------------------------------------ + + clock_divide : process(S_GCLK) + begin + if rising_edge(S_GCLK) then + if S_GRESET = '1' then + clk_counter <= "0000000000000000000000000000"; + else + clk_counter <= clk_counter + '1'; + end if; + end if; + end process; + + clk_div <= clk_counter(0); + S_CLK_OUT <= clk_counter(0); + + +----------------------------------------------------------------------------------- +-- +-- 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 temp 2 for 16 clock cycles. +-- +----------------------------------------------------------------------------------- + +counter : process(clk_div, enParalelLoad, enShiftCounter) + begin + if rising_edge(clk_div) then + if enParalelLoad = '1' then + shiftCounter <= "0000"; + temp1 <= control & DATA1; + temp2 <= control & DATA2; + elsif (enShiftCounter = '1') then + temp1 <= temp1(14 downto 0)&temp1(15); + temp2 <= temp2(14 downto 0)&temp2(15); + shiftCounter <= shiftCounter + '1'; + end if; + end if; + end process; + + S_D1 <= temp1(15); + S_D2 <= temp2(15); + --S_D2 <= S_GCLK; + + DATA1 <= slv_reg1(11 downto 0); + DATA2 <= slv_reg2(11 downto 0); +--------------------------------------------------------------------------------- +-- +-- Title : Finite State Machine +-- +-- Description: This 3 processes represent the FSM that contains three states. +-- First one is the Idle state in which the temporary registers are +-- assigned the updated value of the input "DATA1" and "DATA2". +-- The next state is the ShiftOut state which is the state where the +-- 16-bits of temporary registers are shifted out left from the MSB +-- to the two serial outputs, D1 and D2. Immediately following the +-- second state is the third state SyncData. This state drives the +-- output signal sync high for2 clock signals telling the DAC121S101 +-- to latch the 16-bit data it just recieved in the previous state. +-- Notes: The data will change on the upper 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, S_GRESET) + begin + if rising_edge(clk_div) then + if (S_GRESET = '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'; + S_DONE <='1'; + S_NSYNC <='1'; + enParalelLoad <= '1'; + elsif current_state = ShiftOut then + enShiftCounter <='1'; + S_DONE <='0'; + S_NSYNC <='0'; + enParalelLoad <= '0'; + else --if current_state = SyncData then + enShiftCounter <='0'; + S_DONE <='0'; + S_NSYNC <='1'; + enParalelLoad <= '0'; + end if; + end process; + + + + START <= slv_reg0(0); + + S_LEDS_OUT(0) <= START; + + + + +----------------------------------------------------------------------------------- +-- +-- 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 <= ShiftOut; + end if; + when ShiftOut => + 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; + + + + + + + + -- Implement write response logic generation + -- The write response and response valid signals are asserted by the slave + -- when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. + -- This marks the acceptance of address and indicates the status of + -- write transaction. + + process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + axi_bvalid <= '0'; + axi_bresp <= "00"; --need to work more on the responses + else + if (axi_awready = '1' and S_AXI_AWVALID = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0' ) then + axi_bvalid <= '1'; + axi_bresp <= "00"; + elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then --check if bready is asserted while bvalid is high) + axi_bvalid <= '0'; -- (there is a possibility that bready is always asserted high) + end if; + end if; + end if; + end process; + + -- Implement axi_arready generation + -- axi_arready is asserted for one S_AXI_ACLK clock cycle when + -- S_AXI_ARVALID is asserted. axi_awready is + -- de-asserted when reset (active low) is asserted. + -- The read address is also latched when S_AXI_ARVALID is + -- asserted. axi_araddr is reset to zero on reset assertion. + + process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + axi_arready <= '0'; + axi_araddr <= (others => '1'); + else + if (axi_arready = '0' and S_AXI_ARVALID = '1') then + -- indicates that the slave has acceped the valid read address + axi_arready <= '1'; + -- Read Address latching + axi_araddr <= S_AXI_ARADDR; + else + axi_arready <= '0'; + end if; + end if; + end if; + end process; + + -- Implement axi_arvalid generation + -- axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both + -- S_AXI_ARVALID and axi_arready are asserted. The slave registers + -- data are available on the axi_rdata bus at this instance. The + -- assertion of axi_rvalid marks the validity of read data on the + -- bus and axi_rresp indicates the status of read transaction.axi_rvalid + -- is deasserted on reset (active low). axi_rresp and axi_rdata are + -- cleared to zero on reset (active low). + process (S_AXI_ACLK) + begin + if rising_edge(S_AXI_ACLK) then + if S_AXI_ARESETN = '0' then + axi_rvalid <= '0'; + axi_rresp <= "00"; + else + if (axi_arready = '1' and S_AXI_ARVALID = '1' and axi_rvalid = '0') then + -- Valid read data is available at the read data bus + axi_rvalid <= '1'; + axi_rresp <= "00"; -- 'OKAY' response + elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then + -- Read data is accepted by the master + axi_rvalid <= '0'; + end if; + end if; + end if; + end process; + + -- Implement memory mapped register select and read logic generation + -- Slave register read enable is asserted when valid address is available + -- and the slave is ready to accept the read address. + slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ; + + process (slv_reg0, slv_reg1, slv_reg2, slv_reg3, slv_reg4, slv_reg5, slv_reg6, slv_reg7, slv_reg8, slv_reg9, slv_reg10, slv_reg11, slv_reg12, slv_reg13, slv_reg14, slv_reg15, axi_araddr, S_AXI_ARESETN, slv_reg_rden) + variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0); + begin + -- Address decoding for reading registers + loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB); + case loc_addr is + when b"0000" => + reg_data_out <= slv_reg0; + when b"0001" => + reg_data_out <= slv_reg1; + when b"0010" => + reg_data_out <= slv_reg2; + when b"0011" => + reg_data_out <= slv_reg3; + when b"0100" => + reg_data_out <= slv_reg4; + when b"0101" => + reg_data_out <= slv_reg5; + when b"0110" => + reg_data_out <= slv_reg6; + when b"0111" => + reg_data_out <= slv_reg7; + when b"1000" => + reg_data_out <= slv_reg8; + when b"1001" => + reg_data_out <= slv_reg9; + when b"1010" => + reg_data_out <= slv_reg10; + when b"1011" => + reg_data_out <= slv_reg11; + when b"1100" => + reg_data_out <= slv_reg12; + when b"1101" => + reg_data_out <= slv_reg13; + when b"1110" => + reg_data_out <= slv_reg14; + when b"1111" => + reg_data_out <= slv_reg15; + when others => + reg_data_out <= (others => '0'); + end case; + end process; + + -- Output register or memory read data + process( S_AXI_ACLK ) is + begin + if (rising_edge (S_AXI_ACLK)) then + if ( S_AXI_ARESETN = '0' ) then + axi_rdata <= (others => '0'); + else + if (slv_reg_rden = '1') then + -- When there is a valid read address (S_AXI_ARVALID) with + -- acceptance of read address by the slave (axi_arready), + -- output the read dada + -- Read address mux + axi_rdata <= reg_data_out; -- register read data + end if; + end if; + end if; + end process; + + + -- Add user logic here + + -- User logic ends + +end arch_imp;