From: Jan Michel Date: Tue, 23 Aug 2022 15:14:19 +0000 (+0200) Subject: add automatic ADC reader to Trb3sc Tools. X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=604fc0798586d612ad8c0d78b814c2eae817ff5b;p=trb3sc.git add automatic ADC reader to Trb3sc Tools. Requires a new constant USE_ADC in the config file! --- diff --git a/code/adc_controller.vhd b/code/adc_controller.vhd new file mode 100644 index 0000000..c61d9ed --- /dev/null +++ b/code/adc_controller.vhd @@ -0,0 +1,260 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; +use work.config.all; + +entity adc_controller is + generic ( + CH1_CMD : STD_LOGIC_VECTOR(19 downto 0) := x"1c3cb"; + CH2_CMD : STD_LOGIC_VECTOR(19 downto 0) := x"1d5cb"; + CH3_CMD : STD_LOGIC_VECTOR(19 downto 0) := x"2e3cb"; + CH4_CMD : STD_LOGIC_VECTOR(19 downto 0) := x"2f5cb"; + TMP_CMD : STD_LOGIC_VECTOR(19 downto 0) := x"1F393" + ); + port ( + CLK : in std_logic; + RST : in std_logic; + BUS_RX : in CTRLBUS_RX; + BUS_TX : out CTRLBUS_TX; + + ADC_CS : out std_logic; + ADC_MOSI : out std_logic; + ADC_MISO : in std_logic; + ADC_CLK : out std_logic + ); +end adc_controller; + + +architecture arch of adc_controller is +signal reset_i : std_logic; +signal CONF_reg : std_logic_vector(15 downto 0) := x"0501"; +alias CONF_enable : std_logic is CONF_reg(0); +alias CONF_waittime : std_logic_vector is CONF_reg(15 downto 8); + +signal timer : unsigned(18 downto 0) := (others => '0'); +signal waittime : unsigned(7 downto 0) := (others => '0'); + +signal conf_ram_write : std_logic; +signal conf_ram_dout1, conf_ram_dout2 : std_logic_vector(19 downto 0); +signal channel_select : std_logic_vector(2 downto 0); + +signal result_ram_write : std_logic; +signal result_ram_addr : std_logic_vector(2 downto 0); +signal result_ram_data : std_logic_vector(17 downto 0); +signal result_ram_dout : std_logic_vector(17 downto 0); + +signal next_conf_ack, next_result_ack : std_logic; + +type state_t is (IDLE, WAIT_CONFIG, CONV_CHANNEL, WAIT_CONV, READ_CHANNEL, WAIT_READ, CALC1_CHANNEL, CALC2_CHANNEL, STORE_CHANNEL); +signal state : state_t; + +signal spi_miso_reg, spi_miso_rreg : std_logic; +signal spi_send : std_logic; +signal spi_ready : std_logic; +signal spi_data : std_logic_vector(15 downto 0); +signal spi_dout : std_logic_vector(15 downto 0); +signal spi_bitcount : unsigned(5 downto 0); +signal spi_timer : unsigned(3 downto 0); + +signal result : std_logic_vector(21 downto 0); + +begin + +reset_i <= not CONF_reg(0) or RST; + +THE_CONF_RAM : ram_dp_19x8_preset + generic map( + DEPTH => 3, + WIDTH => 20, + CONTENT => (CH1_CMD, CH2_CMD, CH3_CMD, CH4_CMD, TMP_CMD, x"00000",x"00000",x"00000") + ) + port map( + CLK => CLK, + WR1 => conf_ram_write, + A1 => BUS_RX.addr(2 downto 0), + DOUT1 => conf_ram_dout1, + DIN1 => BUS_RX.data(19 downto 0), + A2 => channel_select, + DOUT2 => conf_ram_dout2 + ); + +THE_RESULT_RAM : ram_dp + generic map( + DEPTH => 3, + WIDTH => 18 + ) + port map( + CLK => CLK, + WR1 => result_ram_write, + A1 => result_ram_addr, + DOUT1 => open, + DIN1 => result_ram_data, + A2 => BUS_RX.addr(2 downto 0), + DOUT2 => result_ram_dout + ); + + +PROC_REGS : process begin + wait until rising_edge(CLK); + next_conf_ack <= '0'; + next_result_ack <= '0'; + BUS_TX.ack <= next_conf_ack or next_result_ack; + + BUS_TX.nack <= '0'; + BUS_TX.unknown <= '0'; + conf_ram_write <= '0'; + + BUS_TX.data <= x"00000000"; + if next_conf_ack='1' then BUS_TX.data <= x"000" & conf_ram_dout1; end if; + if next_result_ack='1' then BUS_TX.data <= x"000" & "00" & result_ram_dout; end if; + + if BUS_RX.write = '1' then + BUS_TX.ack <= '1'; + case BUS_RX.addr(3 downto 0) is + when x"0"|x"1"|x"2"|x"3"|x"4" => conf_ram_write <= '1'; + when x"5" => CONF_reg <= BUS_RX.data(15 downto 0); + when others => BUS_TX.ack <= '0'; + BUS_TX.unknown <= '1'; + end case; + + elsif BUS_RX.read = '1' then + BUS_TX.ack <= '1'; + BUS_TX.data <= (others => '0'); + + case BUS_RX.addr(3 downto 0) is + when x"0"|x"1"|x"2"|x"3"|x"4" => BUS_TX.ack <= '0'; + next_conf_ack <= '1'; + when x"5" => BUS_TX.data(15 downto 0) <= CONF_reg; + when x"8"|x"9"|x"a"|x"b"|x"c" => BUS_TX.ack <= '0'; + next_result_ack <= '1'; + + when others => BUS_TX.ack <= '0'; + BUS_TX.unknown <= '1'; + end case; + + end if; +end process; + +PROC_CONTROL : process begin + wait until rising_edge(CLK); + spi_send <= '0'; + result_ram_write <= '0'; + + if timer = to_unsigned(CLOCK_FREQUENCY*1000,19) then + waittime <= waittime + 1; + timer <= (others => '0'); + else + timer <= timer + 1; + end if; + + case state is + when IDLE => + if CONF_enable = '1' then + state <= WAIT_CONFIG; + channel_select <= 0; + end if; + when WAIT_CONFIG => + state <= CONV_CHANNEL; + when CONV_CHANNEL => + spi_data <= conf_ram_dout2(15 downto 0); + spi_send <= '1'; + waittime <= (others => '0'); + timer <= (others => '0'); + state <= WAIT_CONV; + + when WAIT_CONV => + if waittime = unsigned(CONF_waittime) then + state <= READ_CHANNEL; + end if; + + when READ_CHANNEL => + spi_data <= x"0000"; + spi_send <= '1'; + waittime <= (others => '0'); + timer <= (others => '0'); + state <= WAIT_READ; + + when WAIT_READ => + if waittime = x"01" then + state <= CALC1_CHANNEL; + end if; + + when CALC1_CHANNEL => + result <= (others => '0'); + case conf_ram_dout2(11 downto 9) is + when "001" => result(19 downto 4) <= spi_dout; + when "010" => result(18 downto 3) <= spi_dout; + when "011" => result(17 downto 2) <= spi_dout; + when "100" => result(16 downto 1) <= spi_dout; + when others => result(15 downto 0) <= spi_dout; + end case; + state <= CALC2_CHANNEL; + + when CALC2_CHANNEL => + case conf_ram_dout2(19 downto 16) is + when x"2" => result <= result(20 downto 0) & '0'; + when x"4" => result <= result(19 downto 0) & "00"; + when others => result <= result; + end case; + state <= STORE_CHANNEL; + + when STORE_CHANNEL => + result_ram_data <= result(20 downto 3); + result_ram_addr <= channel_select; + result_ram_write <= '1'; + if channel_select = "100" then + state <= IDLE; + else + state <= WAIT_CONFIG; + channel_select <= std_logic_vector(unsigned(channel_select) + 1); + end if; + end case; + + if RST= '1' then + state <= IDLE; + end if; + +end process; + + +PROC_SPI : process begin + wait until rising_edge(CLK); + spi_miso_reg <= ADC_MISO; + spi_miso_rreg <= spi_miso_reg; + + if spi_send = '1' then + ADC_CS <= '0'; + ADC_CLK <= '0'; + spi_timer <= x"F"; + spi_bitcount <= "100000"; + elsif spi_bitcount /= "111111" then + spi_timer <= spi_timer - 1; + ADC_CLK <= spi_bitcount(0); + ADC_MOSI <= spi_data(to_integer(unsigned(spi_bitcount(4 downto 1)))); + if spi_timer = 0 then + spi_bitcount <= spi_bitcount - 1; + if spi_bitcount(0) = '0' then + spi_dout(to_integer(unsigned(spi_bitcount(4 downto 1)))) <= spi_miso_rreg; + end if; + end if; + else --IDLE + ADC_CS <= '1'; + ADC_CLK <= '0'; + spi_bitcount <= "111111"; + end if; + + + if RST= '1' then + spi_bitcount <= "111111"; + ADC_CS <= '1'; + ADC_CLK <= '0'; + spi_timer <= x"F"; + end if; +end process; + + +end architecture; diff --git a/code/trb3sc_tools.vhd b/code/trb3sc_tools.vhd index e9f228b..772774f 100644 --- a/code/trb3sc_tools.vhd +++ b/code/trb3sc_tools.vhd @@ -10,7 +10,12 @@ library work; entity trb3sc_tools is generic ( - HEADER_PAGE_ADDR : std_logic_vector(15 downto 0) := x"7000" + HEADER_PAGE_ADDR : std_logic_vector(15 downto 0) := x"7000"; + ADC_CMD_1 : std_logic_vector(19 downto 0) := x"2c5cb"; --default values for Trb3sc + ADC_CMD_2 : std_logic_vector(19 downto 0) := x"1d3cb"; + ADC_CMD_3 : std_logic_vector(19 downto 0) := x"1e5cb"; + ADC_CMD_4 : std_logic_vector(19 downto 0) := x"2f3cb"; + ADC_CMD_T : std_logic_vector(19 downto 0) := x"1F393" ); port( CLK : in std_logic; @@ -206,14 +211,36 @@ THE_FLASH_REGS : entity work.load_settings --------------------------------------------------------------------------- -- ADC --------------------------------------------------------------------------- +gen_noadc : if INCLUDE_ADC = 0 generate busadc_tx.unknown <= '1'; busadc_tx.nack <= '0'; busadc_tx.ack <= '0'; busadc_tx.data <= (others => '0'); +end generate; +gen_adc : if INCLUDE_ADC = 1 generate + THE_ADC : adc_controller + generic map( + CH1_CMD => ADC_CMD_1, + CH2_CMD => ADC_CMD_2, + CH3_CMD => ADC_CMD_3, + CH4_CMD => ADC_CMD_4, + TMP_CMD => ADC_CMD_T + ) + port map( + CLK => CLK, + RST => RESET, + BUS_RX => busadc_rx, + BUS_TX => busadc_tx, + ADC_CS => ADC_CS, + ADC_MOSI => ADC_MOSI, + ADC_MISO => ADC_MISO, + ADC_CLK => ADC_CLK + ); +end generate; --------------------------------------------------------------------------- --- ADC +-- LCD --------------------------------------------------------------------------- gen_lcd : if INCLUDE_LCD = 1 generate THE_LCD : entity work.lcd @@ -259,11 +286,13 @@ end generate; SPI_MOSI_OUT <= spi_sdo; spi_sdi <= SPI_MISO_IN(15 downto 9) & HEADER_IO(4) & ADC_MISO & SPI_MISO_IN(6 downto 0); - - ADC_CLK <= not spi_sck(7); - ADC_CS <= spi_cs(7); - ADC_MOSI <= spi_sdo(7); - + + gen_spiadc : if INCLUDE_ADC = 0 generate + ADC_CLK <= not spi_sck(7); + ADC_CS <= spi_cs(7); + ADC_MOSI <= spi_sdo(7); + end generate; + busspi_tx.unknown <= '0'; end generate;