spi_clock_speed : integer := 1e4
);
port(
- clk : in std_logic;
- reset : in std_logic;
- start_write : in std_logic; --start writing data to adc/start conversion
- config_in : in std_logic_vector(15 downto 0); --config data to adc
- spi_data_from_chip : in std_logic; --serial data from dac
- spi_data_to_chip : out std_logic; --seral data to dac shift register
- spi_data_out : out std_logic_vector(31 downto 0); --conversion data and config readback
- spi_clk : out std_logic; --SPI interface clock
- spi_ld : out std_logic); --SPI load/chip select
+ clk : in std_logic;
+ reset : in std_logic;
+ start_write : in std_logic; --start writing data to adc/start conversion
+ config_in : in std_logic_vector(15 downto 0); --config data to adc
+ spi_data_from_chip : in std_logic; --serial data from dac
+ spi_data_to_chip : out std_logic; --seral data to dac shift register
+ spi_data_out : out std_logic_vector(31 downto 0); --conversion data and config readback
+ spi_clk : out std_logic; --SPI interface clock
+ spi_cs : out std_logic); --SPI chip select
end entity ADS1018SPI;
architecture RTL of ADS1018SPI is
-
+
+ constant c_div_cnt_max : integer := fpga_clock_speed/spi_clock_speed;
+ signal div_cnt : integer range 0 to c_div_cnt_max - 1 := 0;
+
+ type ads_fsm_type is (idle, cs_low, sendbit1, sendbit2, cs_high);
+ signal ads_fsm_state : ads_fsm_type := idle;
+
+ signal config_index : integer range 0 to 15 := 15;
+ signal byte_counter : integer range 0 to 31 := 31;
+ signal spi_data_out_i : std_logic_vector(31 downto 0) := (others => '0');
+
begin
+ spi_proc : process(clk) is
+ begin
+ if rising_edge(clk) then
+ if reset = '1' then
+ spi_cs <= '1';
+ spi_clk <= '0';
+ spi_data_to_chip <= '0';
+ spi_data_out <= (others => '0');
+ div_cnt <= 0;
+ else
+ case ads_fsm_state is
+ when idle =>
+ spi_cs <= '1';
+ spi_clk <= '0';
+ spi_data_to_chip <= '0';
+ div_cnt <= 0;
+ if start_write = '1' then
+ config_index <= 15;
+ byte_counter <= 31;
+ spi_cs <= '0';
+ ads_fsm_state <= cs_low;
+ end if;
+ when cs_low =>
+ div_cnt <= div_cnt + 1;
+ if div_cnt = c_div_cnt_max - 1 then
+ div_cnt <= 0;
+ ads_fsm_state <= sendbit1;
+ end if;
+ when sendbit1 =>
+ spi_clk <= '1';
+ spi_data_to_chip <= config_in(config_index);
+ div_cnt <= div_cnt + 1;
+ if div_cnt = c_div_cnt_max/2 then
+ ads_fsm_state <= sendbit2;
+ spi_data_out_i <= spi_data_out_i(30 downto 0) & spi_data_from_chip;
+ end if;
+ when sendbit2 =>
+ spi_clk <= '0';
+ div_cnt <= div_cnt + 1;
+ if div_cnt = c_div_cnt_max - 1 then
+ div_cnt <= 0;
+ byte_counter <= byte_counter - 1;
+ if config_index > 0 then
+ config_index <= config_index - 1;
+ else
+ config_index <= 15;
+ end if;
+ if byte_counter > 0 then
+ byte_counter <= byte_counter - 1;
+ ads_fsm_state <= sendbit1;
+ else
+ ads_fsm_state <= cs_high;
+ end if;
+ end if;
+ when cs_high =>
+ div_cnt <= div_cnt + 1;
+ if div_cnt = c_div_cnt_max - 1 then
+ div_cnt <= 0;
+ spi_cs <= '1';
+ ads_fsm_state <= idle;
+ spi_data_out <= spi_data_out_i;
+ end if;
+ end case;
+ end if;
+ end if;
+ end process spi_proc;
+
end architecture RTL;
spi_clk : out std_logic; --serial clock
spi_din : out std_logic; --serial data out
spi_ld_tmp_dac : out std_logic; --load temperature dac
- spi_ld_adc : out std_logic; --load adc
+ spi_cs_adc : out std_logic; --load adc
spi_ld_thres : out std_logic; --load threshold and injection dac
--slow data signals
hitbus : in std_logic; --hitbus signal
spi_din : out std_logic; --serial data out
spi_ld_tmp_dac : out std_logic; --load temperature dac
spi_ld_thres : out std_logic; --load threshold and injection dac
- spi_ld_adc : out std_logic; --load adc
+ spi_cs_adc : out std_logic; --load adc
--TRB slow control
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
spi_din : out std_logic; --serial data out
spi_ld_tmp_dac : out std_logic; --load temperature dac
spi_ld_thres : out std_logic; --load threshold and injection dac
- spi_ld_adc : out std_logic; --load adc
+ spi_cs_adc : out std_logic; --load adc
--TRB slow control
SLV_READ_IN : in std_logic;
SLV_WRITE_IN : in std_logic;
spi_data_to_chip : out std_logic;
spi_data_out : out std_logic_vector(31 downto 0);
spi_clk : out std_logic;
- spi_ld : out std_logic
+ spi_cs : out std_logic
);
end component ADS1018SPI;
spi_data_to_chip => spi_data_to_chip_adc,
spi_data_out => spi_data_out_adc,
spi_clk => spi_clk_adc,
- spi_ld => spi_ld_adc
+ spi_cs => spi_cs_adc
);
-----------------------------------------------------------------------------
--TRB Slave Bus
--0x0094: temperature dac
--0x0095: readback temperature dac
--0x0096: start write threshold and injection dacs bit
+ --0x0097: write config adc
+ --0x0098: read adc data
-----------------------------------------------------------------------------
SLV_BUS_HANDLER : process(clk)
begin -- process SLV_BUS_HANDLER
SLV_UNKNOWN_ADDR_OUT <= '0';
SLV_NO_MORE_DATA_OUT <= '0';
start_write_threshold <= '0';
+ start_write_temperature <= '0';
+ start_write_adc <= '0';
if SLV_READ_IN = '1' then
case SLV_ADDR_IN is
when x"0095" =>
SLV_DATA_OUT(15 downto 0) <= spi_data_out_temperature;
SLV_ACK_OUT <= '1';
+ when x"0097" =>
+ SLV_DATA_OUT(15 downto 0) <= config_adc;
+ SLV_ACK_OUT <= '1';
+ when x"0098" =>
+ SLV_DATA_OUT <= spi_data_out_adc;
+ SLV_ACK_OUT <= '1';
when others =>
SLV_UNKNOWN_ADDR_OUT <= '1';
end case;
when x"0096" =>
start_write_threshold <= '1';
SLV_ACK_OUT <= '1';
+ when x"0097" =>
+ config_adc <= SLV_DATA_IN(15 downto 0);
+ start_write_adc <= '1';
+ SLV_ACK_OUT <= '1';
when others =>
SLV_UNKNOWN_ADDR_OUT <= '1';
end case;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity ADS1018SPITest is
+end entity ADS1018SPITest;
+
+architecture sim of ADS1018SPITest is
+
+ component ADS1018SPI
+ generic(
+ fpga_clock_speed : integer := 1e8;
+ spi_clock_speed : integer := 1e4
+ );
+ port(
+ clk : in std_logic;
+ reset : in std_logic;
+ start_write : in std_logic;
+ config_in : in std_logic_vector(15 downto 0);
+ spi_data_from_chip : in std_logic;
+ spi_data_to_chip : out std_logic;
+ spi_data_out : out std_logic_vector(31 downto 0);
+ spi_clk : out std_logic;
+ spi_cs : out std_logic
+ );
+ end component ADS1018SPI;
+
+ constant c_fpga_clock_speed : integer := 1e8;
+ constant c_spi_clock_speed : integer := 5e6;
+ constant c_clock_period : time := 10 ns;
+ --dut interface signals
+ signal clk : std_logic;
+ signal reset : std_logic := '0';
+ signal start_write : std_logic := '0';
+ signal config_in : std_logic_vector(15 downto 0) := (others => '0');
+ signal spi_data_from_chip : std_logic;
+ signal spi_data_to_chip : std_logic;
+ signal spi_data_out : std_logic_vector(31 downto 0);
+ signal spi_clk : std_logic;
+ signal spi_cs : std_logic;
+
+ signal config_chip, config_chip_new : std_logic_vector(15 downto 0) := (others => '0');
+ signal data_chip : std_logic_vector(15 downto 0) := x"AACC";
+ signal shiftreg_reg : std_logic_vector(31 downto 0) := (others => '0');
+
+begin
+
+ dut : entity work.ADS1018SPI
+ generic map(
+ fpga_clock_speed => c_fpga_clock_speed,
+ spi_clock_speed => c_spi_clock_speed
+ )
+ port map(
+ clk => clk,
+ reset => reset,
+ start_write => start_write,
+ config_in => config_in,
+ spi_data_from_chip => spi_data_from_chip,
+ spi_data_to_chip => spi_data_to_chip,
+ spi_data_out => spi_data_out,
+ spi_clk => spi_clk,
+ spi_cs => spi_cs
+ );
+
+ ADS_response : process(spi_cs, spi_clk) is
+ begin
+ if spi_cs'event and spi_cs = '0' then
+ shiftreg_reg <= data_chip & config_chip after 100 ns;
+ end if;
+ if spi_cs'event and spi_cs = '1' then
+ config_chip <= config_chip_new;
+ end if;
+ if spi_clk'event and spi_clk = '1' then --on rising clock edge write out new bit
+ spi_data_from_chip <= shiftreg_reg(shiftreg_reg'length - 1);
+ shiftreg_reg <= shiftreg_reg(shiftreg_reg'length - 2 downto 0) & '0' after 100 ns;
+ end if;
+ if spi_clk'event and spi_clk = '0' then --on falling clock edge load new data to config bit
+ config_chip_new <= config_chip_new(config_chip_new'length - 2 downto 0) & spi_data_to_chip;
+ end if;
+ end process ADS_response;
+
+
+ clk_generation : process is
+ begin
+ clk <= '1';
+ wait for c_clock_period/2;
+ clk <= '0';
+ wait for c_clock_period/2;
+ end process clk_generation;
+
+ stimulus : process is
+ begin
+ wait for 100 ns;
+ config_in <= x"BCDB";
+ start_write <= '1';
+ wait for c_clock_period;
+ start_write <= '0';
+ if spi_cs = '0' then
+ wait until spi_cs = '1';
+ end if;
+ wait for 200*c_clock_period;
+ config_in <= x"BCDB";
+ start_write <= '1';
+ wait for c_clock_period;
+ start_write <= '0';
+ wait;
+ end process stimulus;
+
+
+end architecture sim;