This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] ADS1256:串行接口时序 T6和 T11

Guru**** 2537040 points
Other Parts Discussed in Thread: ADS1256

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/1037865/ads1256-serial-interface-timings-t6-and-t11

器件型号:ADS1256

我使用 ADS1256已经有一段时间了、到目前为止、我 已经在发送到 ADS1256或从 ADS1256接收到的每个字节之间插入了 T6延迟、只是为了安全起见、并简化逻辑。 现在、我将考虑提高逻辑效率、并在适用的情况下使用 T11延迟。 但是、我很难理解数据表图1表中的 T11数字。

4 T_CLKIN 对于 RDATA 而言意味着什么? 是其它命令与  RDATA 之间的延迟还是 RDATA 与其它任何命令之间的延迟? 在任何情况  下、在驱动 SCLK 读取采样数据之前、我需要等待 T6 = 50 T_CLKIN、这样我就看不到4 T_CLKIN 的含义。

WREG 呢? T11是构成命令的两个字节之间的时间吗? 还是写入 ADS1256寄存器的字节之间?

唤醒呢? 该命令甚至未在表中列出。

顺便说一下、最好为转换器提供一个仿真模型。 最好在 VHDL 或 Verilog 中。

/F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Fredda、

    让我来看看这一点、很快回来、今天很忙。

    我可以告诉您、很遗憾、我们目前没有任何 Δ-Σ ADC 的仿真模型、包括 ADS1256

    布莱恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Fredda、

    ADS1256具有内部逻辑、需要在命令之间进行某些延迟

    T6用于数据/寄存器回读以获取有效信息的时间。 时间 T11是相邻命令之间的延迟。

    例如、如果发出 RDATA 命令、则需要等待至少4个 tCLK 才能发出任何其他命令。 如果在4个 tCLK (但在50个 tCLK 之前)之后发出另一条命令、RDATA 命令将被中断、并且您将无法在每次 T6上获取 DOUT 上的有效数据。 相反、假设所有其他时序要求都得到满足、新命令将产生影响。 如果您需要此时的数据、则必须重新发出 RDATA 命令并等待时间 T6。

    您无需在多字节命令(例如 RREG、WREG 等)的字节之间等待时间 T11

    WAKEUP 命令后发出另一条命令不需要延迟。

    请告诉我这是否能解答您的问题

    布莱恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢。 这使它更清晰。 因此、我已经尝试尽可能积极地实施逻辑。 下面是数据表中图19的示例。

    WREG_1和 MUX 寄存器="01010001"
    WREG_2 &写入一个寄存器="00000000"
    到 MUX 寄存器的数据="01011000"

    T11 = 4 TCLKIN 在 SYNC 命令之前暂停。 不确定是否需要??

    SYNC 命令="11111100"

    T11 = 24 TCLKIN 在 WAKEUP 命令之前暂停。

    唤醒命令="00000000"
    RDATA  命令="00000001"

    T6 = 50 TCLKIN 在驱动 SCLK 以检索样本数据之前暂停在此

    多路复用 器58h 的数据字节3
    多路复用 器58h 的数据字节2
    多路复用 器58h 的数据字节1



    这似乎是好的。 对此有任何意见吗?

    /F

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Fredda、

    我很高兴现在一切都运转良好。 您是否能够验证转换数据以确保 ADC 正确转换?

    我在您的图中也没有看到 CS 信号(我假设 RDY 信号为 DRDY 信号)。 最好确保正确驱动这是信号。

    我要指出、最大 SCLK 速度为 fCLK/4。 当 fCLK = 7.68MHz (标称值)时、SCLK (最大值)= 1.92MHz。 您的图显示1.99MHz、当然假设您的 fCLK = 7.68MHz、这可能无法正常工作。

    布莱恩

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我没有做过任何广泛的测试、但同时我没有注意到任何奇数样本。 所有采样数据均在预期范围内。

    CS 信号在正常运行期间绑定为低电平。  

    忘记提到 fCLK = 10MHz、因此标称2MHz SCLK 频率应该是可以的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如果有任何人感兴趣、这里是对采用 VHDL 的 ADS1256 ADC 行为进行建模的尝试。 显然、这是数据表的解释、它远非准确、完美、无故障等 小心使用!

    -----------------------------------------------
    -- Description:
    --    The ads1256_tb module emulates an ADS1256 ADC. Note that the emulation is
    --    an interpretation of the information given in the ADS1256 data sheet and that
    --    far from all features are modeled.
    --
    ----------------------------------------------------------------------------------
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.math_real.all;   -- for UNIFORM, TRUNC functions
    
    entity ads1256_tb is
      generic(
        G_ADC_CLOCK_FREQUENCY   : real := 7.68;   -- Unit is MHz
          -- Frequency of externally provided ADC clock
        G_MUX_SET_0             : std_logic_vector(7 downto 0) := x"01";
        G_MUX_SET_1             : std_logic_vector(7 downto 0) := x"23";
        G_MUX_SET_2             : std_logic_vector(7 downto 0) := x"45";
        G_MUX_SET_3             : std_logic_vector(7 downto 0) := x"46";
        G_MUX_SET_4             : std_logic_vector(7 downto 0) := x"78";
        G_MUX_SET_5             : std_logic_vector(7 downto 0) := x"01";
        G_MUX_SET_6             : std_logic_vector(7 downto 0) := x"01";
        G_MUX_SET_7             : std_logic_vector(7 downto 0) := x"01"
          -- The MUX generics define the ADC input configuration in the HW.
        );
      port(
        reset                   : in std_logic; 
        adc_sck                 : in std_logic;
        adc_sdi                 : in std_logic;
        adc_cs_n                : in std_logic;
        adc_rdy_n               : out std_logic; 
        adc_sdo                 : out std_logic
        );
    end ads1256_tb;
    
    architecture rtl of ads1256_tb is
    
      ---------------------------------------------------------------------------
      -- ADS1256 Address mappings constants
      ---------------------------------------------------------------------------
      -- The operation of the ADS1256 is controlled through a set of registers. Collectively, the registers
      -- contain all the information needed to configure the part, such as data rate, multiplexer settings,
      -- PGA setting, calibration, etc., and are listed in Table 23 in the datasheet.
      constant C_STATUS_ADDR        : std_logic_vector (3 downto 0) := x"0";
        -- Status register address
      constant C_MUX_ADDR           : std_logic_vector (3 downto 0) := x"1";
        -- MUX register address
      constant C_ADCON_ADDR         : std_logic_vector (3 downto 0) := x"2";
        -- ADC control register address
      constant C_DRATE_ADDR         : std_logic_vector (3 downto 0) := x"3";
        -- Data rate register address
      constant C_IO_ADDR            : std_logic_vector (3 downto 0) := x"4";
        -- IO register address
      constant C_OFC0_ADDR          : std_logic_vector (3 downto 0) := x"5";
        -- Offset calibration register 0 address
      constant C_OFC1_ADDR          : std_logic_vector (3 downto 0) := x"6";
        -- Offset calibration register 1 address
      constant C_OFC2_ADDR          : std_logic_vector (3 downto 0) := x"7";
        -- Offset calibration register 2 address
      constant C_FSC0_ADDR          : std_logic_vector (3 downto 0) := x"8";
        -- Full-scale calibration register 0 address
      constant C_FSC1_ADDR          : std_logic_vector (3 downto 0) := x"9";
        -- Full-scale calibration register 1 address
      constant C_FSC2_ADDR          : std_logic_vector (3 downto 0) := x"A";
        -- Full-scale calibration register 2 address
      constant C_NUM_OF_REG         : integer := 11;
        -- Total number of registers in the ADS1256 ADC.
    
      ---------------------------------------------------------------------------
      -- ADS1256 Command constants
      ---------------------------------------------------------------------------
      constant C_WAKEUP_CMD         : std_logic_vector (7 downto 0) := x"00";
        -- Completes SYNC and Exits Standby Mode. Also x"FF".
      constant C_RDATA_CMD          : std_logic_vector (7 downto 0) := x"01";
        -- Read Data.
      constant C_RDATAC_CMD         : std_logic_vector (7 downto 0) := x"03";
        -- Read Data Continuously.
      constant C_SDATAC_CMD         : std_logic_vector (7 downto 0) := x"0F";
        -- Stop Read Data Continuously.
      constant C_RREG_B1_CMD        : std_logic_vector (3 downto 0) := x"1";
        -- The constant is the upper nibble of byte 1 of the ADC register
        -- read command. It constitute the actual command. The lower
        -- nibble of Byte 1 of the ADC register read command sets the
        -- address of the register to read and is set in the FPGA logic.
      constant C_RREG_B2_CMD        : std_logic_vector (3 downto 0) := x"0";
        -- The constant is the upper nibble of byte 2 of the ADC register
        -- read command. It constitute the actual command. The lower
        -- nibble of Byte 2 of the ADC register read command sets the
        -- number of registers to read and is set in the FPGA logic.
        -- If multiple registers are read, the lower nibble of
        -- byte 1 of the ADC register read command sets the address
        -- of the starting register.
      constant C_RREG_CMD_NOB       : integer := 2;
        -- Number of bytes in the read register command.
      constant C_WREG_B1_CMD        : std_logic_vector (3 downto 0) := x"5";
        -- The constant is the upper nibble of byte 1 of the ADC register
        -- write command. It constitute the actual command. The lower
        -- nibble of Byte 1 of the ADC register write command sets the
        -- address of the register to write and is set in the FPGA logic.
      constant C_WREG_B2_CMD        : std_logic_vector (3 downto 0) := x"0";
        -- The constant is the upper nibble of byte 2 of the ADC register
        -- write command. It constitute the actual command. The lower
        -- nibble of Byte 2 of the ADC register write command sets the
        -- number of registers to write and is set in the FPGA logic.
        -- If multiple registers are written, the lower nibble of
        -- byte 1 of the ADC register write command sets the address
        -- of the starting register.
      constant C_WREG_CMD_NOB       : integer := 2;
        -- Number of bytes in the write register command.
      constant C_SELFCAL_CMD        : std_logic_vector (7 downto 0) := x"F0";
        -- Offset and Gain Self-Calibration.
      constant C_SELFOCAL_CMD       : std_logic_vector (7 downto 0) := x"F1";
        -- Offset Self-Calibration.
      constant C_SELFGCAL_CMD       : std_logic_vector (7 downto 0) := x"F2";
        -- Gain Self-Calibration.
      constant C_SYSOCAL_CMD        : std_logic_vector (7 downto 0) := x"F3";
        -- System Offset Calibration.
      constant C_SYSGCAL_CMD        : std_logic_vector (7 downto 0) := x"F4";
        -- System Gain Calibration.
      constant C_SYNC_CMD           : std_logic_vector (7 downto 0) := x"FC";
        -- Synchronize the A/D Conversion
      constant C_STANDBY_CMD        : std_logic_vector (7 downto 0) := x"FD";
        -- Begin Standby Mode
      constant C_RESET_CMD          : std_logic_vector (7 downto 0) := x"FE";
        -- Reset to Power-Up Values
      constant C_RDATA_NOB          : integer := 3;
        -- Number of bytes returned by the ADC after a C_RDATA_CMD command.
    
      ---------------------------------------------------------------------------
      -- ADS1256 Timing constants
      ---------------------------------------------------------------------------
      constant C_INT_ADC_CLOCK_FREQ         : real    := G_ADC_CLOCK_FREQUENCY*10.0;  -- Unit is MHz.
        -- Run the "internal" ADC clock 10 times faster than the external ADC
        -- clock driving the real ADC.
      constant C_ADS1256_T6_50              : real    := 50.0/G_ADC_CLOCK_FREQUENCY;  -- Unit is us.
        -- Delay from last SCLK edge for DIN to first SCLK rising edge for
        -- DOUT: RDATA, RDATAC, RREG Commands.
      constant C_ADS1256_T11_4              : real    := 4.0/G_ADC_CLOCK_FREQUENCY;  -- Unit is us.
        -- Final SCLK falling edge of command to first rising edge of next command.
        -- For RREG, WREG and RDATA commands.
      constant C_ADS1256_T11_24             : real    := 24.0/G_ADC_CLOCK_FREQUENCY;  -- Unit is us.
        -- Final SCLK falling edge of command to first rising edge of next command.
        -- For RDATAC and SYNC commands.
    
      ---------------------------------------------------------------------------
      -- Types
      ---------------------------------------------------------------------------
      type t_arr0_10_slv7_0 is array (0 to 10) of std_logic_vector(7 downto 0);
      type adc_state_type is (ST_IDLE, ST_PROCESS_DATA, ST_WREG_B2_CMD, ST_RREG_B2_CMD,
                              ST_WREG, ST_RREG, ST_SEND_ADC_DATA, ST_SELFCAL, ST_SYNC, ST_WAKEUP, ST_RESET);
      type spi_if_state_type is (ST_IDLE, ST_RECEIVING_DATA, ST_SENDING_DATA, ST_SPI_IF_BUSY);
      
      ---------------------------------------------------------------------------
      -- Other constants
      ---------------------------------------------------------------------------
      constant C_ADC_REG_BANK_RESET_VALUE   : t_arr0_10_slv7_0 := ("XXXX0001",  -- 0
                                                                   "00000001",  -- 1
                                                                   "00100000",  -- 2
                                                                   "11110000",  -- 3
                                                                   "11100000",  -- 4
                                                                   "XXXXXXXX",  -- 5
                                                                   "XXXXXXXX",  -- 6
                                                                   "XXXXXXXX",  -- 7
                                                                   "XXXXXXXX",  -- 8
                                                                   "XXXXXXXX",  -- 9
                                                                   "XXXXXXXX"); -- 10
        -- Reset array for the ADC registers. Values according to ADS1256 datasheet.
    
      ---------------------------------------------------------------------------
      -- Signals
      ---------------------------------------------------------------------------
      
      -- FSM signals
      signal adc_state    : adc_state_type    := ST_IDLE;
      signal spi_if_state : spi_if_state_type := ST_IDLE;
      
      -- Clock signals
      signal clk                  : std_logic := '0';
    
      -- Edge finding signals
      signal adc_sck_r1           : std_logic := '0';
      signal adc_sck_r2           : std_logic := '0';
      signal adc_sck_r3           : std_logic := '0';
      signal adc_sdi_r1           : std_logic := '0';
      signal adc_sdi_r2           : std_logic := '0';
      signal adc_cs_n_r1          : std_logic := '0';
      signal adc_cs_n_r2          : std_logic := '0';
      signal adc_sck_pos_edg      : std_logic := '0';
      signal adc_sck_neg_edg      : std_logic := '0';
    
      -- ADC control process (adc_control_proc) signals
      signal send_byte            : std_logic := '0';
      signal deassert_adc_rdy_n   : std_logic := '0';
      signal adc_reg_addr         : integer range 0 to 15 := 0;
      signal num_of_reg           : integer range 0 to 15 := 0;
      signal adc_reg_bank         : t_arr0_10_slv7_0 := C_ADC_REG_BANK_RESET_VALUE;
      signal reg_cnt              : integer range 0 to 15 := 0;
      signal data_to_fpga         : std_logic_vector(7 downto 0) := (others => '0');
      signal calibration_active   : std_logic := '0';
      signal t11_4                : std_logic := '0';
      signal t11_24               : std_logic := '0';
      signal t6                   : std_logic := '0';
    
      -- ADC data and sample control
      signal data_o_reg           : std_logic_vector(23 downto 0) := (others => '0');
      signal adc_data_00          : unsigned(23 downto 0) := x"000000";
      signal adc_data_01          : unsigned(23 downto 0) := x"111111";
      signal adc_data_02          : unsigned(23 downto 0) := x"222222";
      signal adc_data_03          : unsigned(23 downto 0) := x"333333";
      signal adc_data_04          : unsigned(23 downto 0) := x"444444";
      signal adc_data_05          : unsigned(23 downto 0) := x"555555";
      signal adc_data_06          : unsigned(23 downto 0) := x"666666";
      signal adc_data_07          : unsigned(23 downto 0) := x"777777";
      signal updating_sample      : std_logic := '0';
      signal sample_ready         : std_logic := '0';
    
      -- ADC timing signals
      signal calib_cnt            : integer range 0 to positive(500.0*C_INT_ADC_CLOCK_FREQ) - 1 := 0;
      signal calib_done           : std_logic := '0';
      signal sample_period_cnt    : integer range 0 to positive(50000.0*C_INT_ADC_CLOCK_FREQ) := 0;
      signal sample_period        : integer range 0 to positive(2.0*50000.0*C_INT_ADC_CLOCK_FREQ) := 0;
    
      -- SPI interface process (spi_interface_proc) signals
      signal fpga_data_received   : std_logic := '0';
      signal sending_data         : std_logic := '0';
      signal spi_if_busy          : std_logic := '0';
      signal data_from_fpga       : std_logic_vector(7 downto 0) := (others => '0');
      signal bit_cnt              : integer range 0 to 7 := 7;
      signal t_busy_cnt           : integer range 0 to 511 := 0;
      signal t_value              : integer range 0 to 511 := 0;
      signal t_busy               : std_logic := '0';
    
    begin
    
      clk <= not clk after integer((1000000.0/C_INT_ADC_CLOCK_FREQ)/2.0) * 1 ps;
    
      -- Antimeta
      antimeta_proc : process(clk)
      begin
        if rising_edge(clk) then
          adc_sck_r1  <= adc_sck;
          adc_sck_r2  <= adc_sck_r1;
          adc_sdi_r1  <= adc_sdi;
          adc_sdi_r2  <= adc_sdi_r1;
          adc_cs_n_r1 <= adc_cs_n;
          adc_cs_n_r2 <= adc_cs_n_r1;
        end if;
      end process;
    
      -- Find positive and negative edges of adc_sck_r2.
      adc_sck_edge_proc : process(clk)
      begin
        if rising_edge(clk) then
          adc_sck_pos_edg <= '0';
          adc_sck_neg_edg <= '0';
          adc_sck_r3 <= adc_sck_r2;
          if adc_sck_r2 = '1' and adc_sck_r3 = '0' then
            adc_sck_pos_edg <= '1';
          end if;
          if adc_sck_r2 = '0' and adc_sck_r3 = '1' then
            adc_sck_neg_edg <= '1';
          end if;
        end if;
      end process;
     
      -- The adc_control_proc process models the ADC command execution.
      adc_control_proc : process(clk)
        variable seed1  : positive;  -- Seed values for random generator
        variable seed2  : positive;  -- Seed values for random generator
        variable rand1  : real;      -- Random real number value in range 0 to 1.0
      begin
        if rising_edge(clk) then
          if reset = '1' then
            send_byte           <= '0';
            deassert_adc_rdy_n  <= '0';
            adc_state           <= ST_IDLE;
            adc_reg_addr        <= 0;
            num_of_reg          <= 0;
            adc_reg_bank        <= C_ADC_REG_BANK_RESET_VALUE;
            reg_cnt             <= 0;
            data_to_fpga        <= (others => '0');
            calibration_active  <= '0';
            t11_4               <= '0';
            t11_24              <= '0';
            t6                  <= '0';
          else
            send_byte           <= '0';
            deassert_adc_rdy_n  <= '0';
            t11_4               <= '0';
            t11_24              <= '0';
            t6                  <= '0';
            if adc_cs_n_r2 = '1' then    -- A logic high on Chip Select resets the ADC SPI interface.
              send_byte           <= '0';
              deassert_adc_rdy_n  <= '0';
              adc_state           <= ST_IDLE;
              adc_reg_addr        <= 0;
              num_of_reg          <= 0;
              reg_cnt             <= 0;
              data_to_fpga        <= (others => '0');
              calibration_active  <= '0';
            else
              case adc_state is
                when ST_IDLE =>
                  if fpga_data_received = '1' then
                    adc_state <= ST_PROCESS_DATA;
                  end if;
                when ST_PROCESS_DATA =>
                  if data_from_fpga(7 downto 4) = C_WREG_B1_CMD then
                    adc_reg_addr  <= to_integer(unsigned(data_from_fpga(3 downto 0)));
                    adc_state     <= ST_WREG_B2_CMD;
                  elsif data_from_fpga(7 downto 4) = C_RREG_B1_CMD then
                    adc_reg_addr <= to_integer(unsigned(data_from_fpga(3 downto 0)));
                    adc_state <= ST_RREG_B2_CMD;
                  else
                    case data_from_fpga is 
                      when C_WAKEUP_CMD =>
                        adc_state <= ST_WAKEUP;
                      when C_RDATA_CMD =>
                        t6        <= '1';
                        adc_state <= ST_SEND_ADC_DATA;
                      when C_RDATAC_CMD =>
                        t6        <= '1';
                        adc_state <= ST_IDLE;
                      when C_SDATAC_CMD =>
                        t11_24    <= '1';   --???
                        adc_state <= ST_IDLE;
                      when C_SELFCAL_CMD =>
                        adc_state <= ST_SELFCAL;
                      when C_SYNC_CMD =>
                        t11_24    <= '1';
                        adc_state <= ST_SYNC;
                      when C_STANDBY_CMD =>
                        adc_state <= ST_IDLE;
                      when C_RESET_CMD =>
                        adc_state <= ST_RESET;
                      when others =>
                        adc_state <= ST_IDLE;
                    end case;
                  end if;
                when ST_WREG_B2_CMD =>
                  if fpga_data_received = '1' then
                    num_of_reg  <= to_integer(unsigned(data_from_fpga(3 downto 0)));
                    adc_state   <= ST_WREG;
                  end if;
                when ST_RREG_B2_CMD =>
                  if fpga_data_received = '1' then
                    t6          <= '1';
                    num_of_reg  <= to_integer(unsigned(data_from_fpga(3 downto 0)));
                    adc_state   <= ST_RREG;
                  end if;
                when ST_WREG =>
                  if fpga_data_received = '1' then
                    adc_reg_bank(adc_reg_addr + reg_cnt) <= data_from_fpga;
                    if reg_cnt < num_of_reg then
                      reg_cnt <= reg_cnt + 1;
                    else
                      reg_cnt   <= 0;
                      t11_4     <= '1';
                      adc_state <= ST_IDLE;
                    end if;
                  end if;
                when ST_RREG =>
                  if spi_if_busy = '0' then
                    send_byte <= '1';
                    data_to_fpga <= adc_reg_bank(adc_reg_addr + reg_cnt);
                    if reg_cnt < num_of_reg then
                      reg_cnt <= reg_cnt + 1;
                    else
                      reg_cnt   <= 0;
                      adc_state <= ST_IDLE;
                    end if;
                  end if;
                when ST_SEND_ADC_DATA =>
                  if spi_if_busy = '0' then
                    send_byte     <= '1';
                    data_to_fpga  <= data_o_reg(23 - 8*reg_cnt downto 16 - 8*reg_cnt);
                    if reg_cnt < 2 then
                      reg_cnt <= reg_cnt + 1;
                    else
                      deassert_adc_rdy_n <= '1';
                      reg_cnt   <= 0;
                      adc_state <= ST_IDLE;
                    end if;
                  end if;
                when ST_SELFCAL =>
                  calibration_active <= '1';
                  if calib_done = '1' then
                    uniform(seed1, seed2, rand1);
                    adc_reg_bank(to_integer(unsigned(C_OFC0_ADDR))) <= std_logic_vector(to_unsigned(integer(rand1*255.0*0.2), 8));
                    adc_reg_bank(to_integer(unsigned(C_OFC1_ADDR))) <= std_logic_vector(to_unsigned(integer(rand1*255.0*0.4), 8));
                    adc_reg_bank(to_integer(unsigned(C_OFC2_ADDR))) <= std_logic_vector(to_unsigned(integer(rand1*255.0*0.6), 8));
                    adc_reg_bank(to_integer(unsigned(C_FSC0_ADDR))) <= std_logic_vector(to_unsigned(integer(rand1*255.0*0.8), 8));
                    adc_reg_bank(to_integer(unsigned(C_FSC1_ADDR))) <= std_logic_vector(to_unsigned(integer(rand1*255.0*0.9), 8));
                    adc_reg_bank(to_integer(unsigned(C_FSC2_ADDR))) <= std_logic_vector(to_unsigned(integer(rand1*255.0*1.0), 8));
                    calibration_active <= '0';
                    adc_state <= ST_IDLE;
                  end if;
                when ST_SYNC =>
                  adc_state <= ST_IDLE;
                when ST_WAKEUP =>
                  adc_state <= ST_IDLE;
                when ST_RESET =>  -- After releasing from RESET, self-calibration is performed, regardless of the reset method or the state of the ACAL bit before RESET.
                  adc_reg_bank  <= C_ADC_REG_BANK_RESET_VALUE;
                  adc_state     <= ST_SELFCAL;
                when others =>
                  adc_state <= ST_IDLE;
              end case;
            end if;
          end if;
        end if;
      end process;
    
      -- The calibration_proc process models the self-calibration time. The calibration time
      -- actually depends on the PGA and the data rate setting, but that dependency is not modeled here.
      calibration_proc : process(clk)
      begin
        if rising_edge(clk) then
          if reset = '1' then
            calib_cnt <= 0;
            calib_done <= '0';
          else
            calib_done <= '0';
            if calibration_active = '1' then
              if calib_cnt < positive(500.0*C_INT_ADC_CLOCK_FREQ) - 1 then
                calib_cnt <= calib_cnt + 1;
              else
                calib_cnt <= 0;
                calib_done <= '1';
              end if;
            else
              calib_cnt <= 0;
              calib_done <= '0';
            end if;
          end if;
        end if;
      end process;
      
      -- Assign data to adc_data_xx. Depends on the MUX setting (register C_MUX_ADDR).
      -- Only assign static data for making the test bench less complex.
      -- Also, it makes it is easier to see if the MUX setting is effective.
      -- The data_o_reg represents the ADC sample data output register, which isn't updated until
      -- the sample_ready signal is asserted. Otherwise the output data would change as soon
      -- as the MUX setting changes, which wouldn't model the ADC correctly.
      adc_data_proc : process(clk)
      begin
        if rising_edge(clk) then
          if reset = '1' then
            adc_data_00 <= x"000000";
            adc_data_01 <= x"111111";
            adc_data_02 <= x"222222";
            adc_data_03 <= x"333333";
            adc_data_04 <= x"444444";
            adc_data_05 <= x"555555";
            adc_data_06 <= x"666666";
            adc_data_07 <= x"777777";
            data_o_reg  <= (others => '0');
          else
            if sample_ready = '1' then
              if adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_0 then
                adc_data_00 <= adc_data_00 + 1;
                data_o_reg <= std_logic_vector(adc_data_00);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_1 then
                adc_data_01 <= adc_data_01 + 1;
                data_o_reg <= std_logic_vector(adc_data_01);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_2 then
                adc_data_02 <= adc_data_02 + 1;
                data_o_reg <= std_logic_vector(adc_data_02);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_3 then
                adc_data_03 <= adc_data_03 + 1;
                data_o_reg <= std_logic_vector(adc_data_03);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_4 then
                adc_data_04 <= adc_data_04 + 1;
                data_o_reg <= std_logic_vector(adc_data_04);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_5 then
                adc_data_05 <= adc_data_05 + 1;
                data_o_reg <= std_logic_vector(adc_data_05);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_6 then
                adc_data_06 <= adc_data_06 + 1;
                data_o_reg <= std_logic_vector(adc_data_06);
              elsif adc_reg_bank(to_integer(unsigned(C_MUX_ADDR))) = G_MUX_SET_7 then
                adc_data_07 <= adc_data_07 + 1;
                data_o_reg <= std_logic_vector(adc_data_07);
              end if;
            end if;
          end if;
        end if;
      end process;
    
      -- The data_rate_proc process sets the ADC sampling period, which depends on the data rate setting
      -- given by register C_DRATE_ADDR.
      -- The periods are not the actual values since the simulation would take too long with real values.
      -- Also, the period depends on the ADS1256 master clock. The period values below are 1/10, 1/100 or 1/1000.
      -- of the real values for a ADS1256 master clock = 7.68 MHz.
      data_rate_proc : process(clk)
      begin
        if rising_edge(clk) then
          if reset = '1' then
            sample_period <= positive(100.0*C_INT_ADC_CLOCK_FREQ);
          else
            case adc_reg_bank(to_integer(unsigned(C_DRATE_ADDR))) is
              when "11110000" =>    -- 30 000
                sample_period <= positive(2.0*3.3*C_INT_ADC_CLOCK_FREQ);
              when "11100000" =>    -- 15 000
                sample_period <= positive(2.0*6.7*C_INT_ADC_CLOCK_FREQ);
              when "11010000" =>    -- 7 500
                sample_period <= positive(2.0*13.3*C_INT_ADC_CLOCK_FREQ);
              when "11000000" =>    -- 3 750
                sample_period <= positive(2.0*26.6*C_INT_ADC_CLOCK_FREQ);
              when "10110000" =>    -- 2 000
                sample_period <= positive(2.0*5.0*C_INT_ADC_CLOCK_FREQ);
              when "10100001" =>    -- 1 000
                sample_period <= positive(2.0*10.0*C_INT_ADC_CLOCK_FREQ);
              when "10010010" =>    -- 500
                sample_period <= positive(2.0*20.0*C_INT_ADC_CLOCK_FREQ);
              when "10000010" =>    -- 100
                sample_period <= positive(2.0*100.0*C_INT_ADC_CLOCK_FREQ);
              when "01110010" =>    -- 60
                sample_period <= positive(2.0*166.6*C_INT_ADC_CLOCK_FREQ);
              when "01100011" =>    -- 50
                sample_period <= positive(2.0*200.0*C_INT_ADC_CLOCK_FREQ);
              when "01010011" =>    -- 30
                sample_period <= positive(2.0*333.3*C_INT_ADC_CLOCK_FREQ);
              when "01000011" =>    -- 25
                sample_period <= positive(2.0*400.0*C_INT_ADC_CLOCK_FREQ);
              when "00110011" =>    -- 15
                sample_period <= positive(2.0*666.6*C_INT_ADC_CLOCK_FREQ);
              when "00100011" =>    -- 10
                sample_period <= positive(2.0*111.0*C_INT_ADC_CLOCK_FREQ);
              when "00010011" =>    -- 5
                sample_period <= positive(2.0*222.0*C_INT_ADC_CLOCK_FREQ);
              when "00000011" =>    -- 2.5
                sample_period <= positive(2.0*500.0*C_INT_ADC_CLOCK_FREQ);
              when others =>
                sample_period <= positive(100.0*C_INT_ADC_CLOCK_FREQ);
            end case;
          end if;
        end if;
      end process;
    
      -- The sample_proc process counts the sampling period and controls, together with the adc_rdy_proc process, the assertion of adc_rdy_n.
      -- adc_rdy_n goes low to indicate that a sample is ready. After all 24 bits have been shifted out on adc_sdo,
      -- adc_rdy_n goes high. It is not necessary to read back all 24 bits, but adc_rdy_n will then not return high until new
      -- data is being updated. This is modeled by the updating_sample signal. It takes 16 ADC master clock cycles to update
      -- the ADC data. t17 in the ADS1256 datasheet.
      -- adc_rdy_n = /DRDY, adc_sdo = DOUT
      sample_proc : process(clk)
      begin
        if rising_edge(clk) then
          if reset = '1' then
            sample_period_cnt <= 0;
            sample_ready <= '0';
            updating_sample <= '0';
          else
            sample_ready <= '0';
            if sample_period_cnt = sample_period - 16 then
              updating_sample <= '1';
            else
              updating_sample <= '0';
            end if;
            if calibration_active = '1' then
              sample_period_cnt  <= 0;
            elsif sample_period_cnt < sample_period - 1 then
              sample_period_cnt <= sample_period_cnt + 1;
            else
              sample_period_cnt   <= 0;
              sample_ready <= '1';
            end if;
          end if;
        end if;
      end process;
      
      -- The adc_rdy_proc process controls the assertion of adc_rdy_n.
      adc_rdy_proc : process(clk)
      begin
        if rising_edge(clk) then
          if reset = '1' then
            adc_rdy_n <= '1';
          else
            if calibration_active = '1' then
              adc_rdy_n <= '1';
            elsif updating_sample = '1' then
              adc_rdy_n <= '1';
            elsif sample_ready = '1' then
              adc_rdy_n <= '0';
            elsif deassert_adc_rdy_n = '1' then
              adc_rdy_n <= '1';
            end if;
          end if;
        end if;
      end process;
    
      spi_if_busy <= sending_data or send_byte or t6 or t11_4 or t11_24 or t_busy;
    
      -- The spi_interface_proc process controls the adc_sdi and adc_sdo data interface.
      -- Not modeled:
      --    - If SCLK is held low for 32 DRDY periods, the serial interface will reset and the
      --      next SCLK pulse will start a new communication cycle.
      --    - A special pattern on SCLK will reset the chip.
      --
      -- The ST_SPI_IF_BUSY state models the t6 and t11 ADC SPI serial interface timings.
      spi_interface_proc : process(clk)
      begin
        if rising_edge(clk) then
          if reset = '1' then
            fpga_data_received  <= '0';
            sending_data        <= '0';
            spi_if_state        <= ST_IDLE;
            data_from_fpga      <= (others => '0');
            bit_cnt             <= 7;
            adc_sdo             <= 'Z';
            t_value             <= 0;
            t_busy_cnt          <= 0;
            t_busy              <= '0';
          else
            fpga_data_received <= '0';
            if adc_cs_n_r2 = '1' then    -- A logic high on Chip Select resets the ADC SPI interface.
              fpga_data_received  <= '0';
              sending_data        <= '0';
              spi_if_state        <= ST_IDLE;
              data_from_fpga      <= (others => '0');
              bit_cnt             <= 7;
              adc_sdo             <= 'Z'; -- When CS is taken high, the serial interface is reset and DOUT enters a high impedance state. 
              t_value             <= 0;
              t_busy_cnt          <= 0;
              t_busy              <= '0';
            else
              case spi_if_state is
                when ST_IDLE =>
                  if t6 = '1' then
                    spi_if_state  <= ST_SPI_IF_BUSY;
                    t_value       <= positive(C_ADS1256_T6_50*C_INT_ADC_CLOCK_FREQ) - 6;  -- Compensate for inter process communications.
                    t_busy        <= '1';
                  elsif t11_4 = '1' then
                    spi_if_state  <= ST_SPI_IF_BUSY;
                    t_value       <= positive(C_ADS1256_T11_4*C_INT_ADC_CLOCK_FREQ) - 5; 
                    t_busy        <= '1';
                  elsif t11_24 = '1' then
                    spi_if_state  <= ST_SPI_IF_BUSY;
                    t_value       <= positive(C_ADS1256_T11_24*C_INT_ADC_CLOCK_FREQ) - 5;
                    t_busy        <= '1';
                  elsif send_byte = '1' then
                    sending_data  <= '1';
                    spi_if_state  <= ST_SENDING_DATA;
                  elsif adc_sck_pos_edg = '1' then
                    spi_if_state  <= ST_RECEIVING_DATA;
                  end if;
                when ST_RECEIVING_DATA =>
                  if adc_sck_neg_edg = '1' then
                    data_from_fpga(bit_cnt) <= adc_sdi_r2;
                    if bit_cnt > 0 then
                      bit_cnt <= bit_cnt - 1;
                    else
                      fpga_data_received  <= '1';
                      bit_cnt             <= 7;
                      spi_if_state        <= ST_IDLE ;
                    end if;
                  end if;
                when ST_SENDING_DATA =>
                  if adc_sck_pos_edg = '1' then
                    adc_sdo <= data_to_fpga(bit_cnt);
                    if bit_cnt > 0 then
                      bit_cnt <= bit_cnt - 1;
                    else
                      sending_data  <= '0';
                      bit_cnt       <= 7;
                      spi_if_state <= ST_IDLE ;
                    end if;
                  end if;
                when ST_SPI_IF_BUSY =>
                  if t_busy_cnt < t_value - 1 then
                    t_busy_cnt <= t_busy_cnt + 1;
                  else
                    t_busy_cnt    <= 0;
                    t_busy        <= '0';
                    spi_if_state  <= ST_IDLE;
                  end if;
                when others =>
                  spi_if_state  <= ST_IDLE;
              end case;
            end if;
          end if;
        end if;
      end process;
      
    
    end rtl;
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Fredda、这将对任何访问 E2E 论坛的人都可见且有用!

    布莱恩