]> jspc29.x-matter.uni-frankfurt.de Git - trb3sc.git/commitdiff
add automatic ADC reader to Trb3sc Tools.
authorJan Michel <j.michel@gsi.de>
Tue, 23 Aug 2022 15:14:19 +0000 (17:14 +0200)
committerJan Michel <j.michel@gsi.de>
Tue, 23 Aug 2022 15:14:19 +0000 (17:14 +0200)
Requires a new constant USE_ADC in the config file!

code/adc_controller.vhd [new file with mode: 0644]
code/trb3sc_tools.vhd

diff --git a/code/adc_controller.vhd b/code/adc_controller.vhd
new file mode 100644 (file)
index 0000000..c61d9ed
--- /dev/null
@@ -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;
index e9f228b0f1c981c6420eca483bc301afb5c88dc2..772774f14b1c7c86457c44603fcb27e6ff84c345 100644 (file)
@@ -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;