OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [VHDL/] [adc128s022.vhd] - Blame information for rev 324

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 315 jshamlet
-- Copyright (c)2023 Jeremy Seth Henry
2
-- All rights reserved.
3
--
4
-- Redistribution and use in source and binary forms, with or without
5
-- modification, are permitted provided that the following conditions are met:
6
--     * Redistributions of source code must retain the above copyright
7
--       notice, this list of conditions and the following disclaimer.
8
--     * Redistributions in binary form must reproduce the above copyright
9
--       notice, this list of conditions and the following disclaimer in the
10
--       documentation and/or other materials provided with the distribution,
11
--       where applicable (as part of a user interface, debugging port, etc.)
12
--
13
-- THIS SOFTWARE IS PROVIDED BY JEREMY SETH HENRY ``AS IS'' AND ANY
14
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
-- DISCLAIMED. IN NO EVENT SHALL JEREMY SETH HENRY BE LIABLE FOR ANY
17
-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
-- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
--
24
-- VHDL units : adc12s022
25
-- Description: Provides higher-level control of a single ADC128S022 12-bit ADC
26
-- Note that the base part has a maximum Fsclk of 3.2MHz. Note that to simplify
27
--  downstream logic, the data is expanded to a 16-bit bus.
28
--
29
-- Revision History
30
-- Author          Date     Change
31
------------------ -------- ---------------------------------------------------
32
-- Seth Henry      05/18/23 Initial Upload
33
 
34
library ieee;
35
use ieee.std_logic_1164.all;
36
use ieee.std_logic_unsigned.all;
37
use ieee.std_logic_arith.all;
38
use ieee.std_logic_misc.all;
39
 
40
entity adc12s022 is
41
generic(
42
  Clock_Frequency            : real;
43
  Reset_Level                : std_logic := '1'
44
);
45
port(
46
  Clock                      : in  std_logic;
47
  Reset                      : in  std_logic;
48
  --
49 317 jshamlet
  Reinit                     : in  std_logic := '0'; -- Optional sync reset
50 315 jshamlet
  --
51
  RAW_Channel                : out std_logic_vector(2 downto 0);
52
  RAW_Data                   : out std_logic_vector(15 downto 0);
53
  RAW_Valid                  : out std_logic;
54
  --
55
  Busy_In                    : in  std_logic;
56
  --
57
  SDO                        : in  std_logic;
58
  SDI                        : out std_logic;
59
  SCLK                       : out std_logic;
60
  CSn                        : out std_logic
61
);
62
end entity;
63
 
64
architecture behave of adc12s022 is
65
 
66
  -- The ceil_log2 function returns the minimum register width required to
67
  --  hold the supplied integer.
68
  function ceil_log2 (x : in natural) return natural is
69
    variable retval          : natural;
70
  begin
71
    retval                   := 1;
72
    while ((2**retval) - 1) < x loop
73
      retval                 := retval + 1;
74
    end loop;
75
    return retval;
76
  end function;
77
 
78
  -- Per the datasheet, the _022 part has a Fsmax of 3.2MHz, which results in
79
  --  a maximum single-channel conversion rate of 200ksps, or maximum
80
  --  multiplexed rate of 25ksps.
81
  constant ADS128S022_FSCLK  : real := 3200000.0;
82
 
83
  constant Clock_Ratio       : real :=
84
    ((Clock_Frequency + (0.5*ADS128S022_FSCLK)) / ADS128S022_FSCLK);
85
 
86
  constant Half_Period_Clks  : integer := integer(Clock_Ratio * 0.5);
87
 
88
  type ADC_STATES is ( INIT, IDLE, REQ_SP, SP_WAIT, INC_CH );
89
  signal ADC_State           : ADC_STATES := INIT;
90
 
91
  signal Channel             : std_logic_vector(2 downto 0) := "000";
92
  signal Conv_Start          : std_logic := '0';
93
 
94
  signal Data_Out            : std_logic_vector(11 downto 0) :=
95
                                 (others => '0');
96
  signal Valid               : std_logic := '0';
97
 
98
  constant Clk_Div_i         : integer := Half_Period_Clks - 1;
99
  constant Clk_Div_Bits      : integer := ceil_log2(Clk_Div_i);
100
  constant CLK_DIV_VAL       : std_logic_vector(Clk_Div_Bits - 1 downto 0) :=
101
                                conv_std_logic_vector(Clk_Div_i,Clk_Div_Bits);
102
  signal HT_Cntr             : std_logic_vector(Clk_Div_Bits - 1 downto 0);
103
  signal HT_Tick             : std_logic := '0';
104
 
105
  type SPI_STATES is ( IDLE, ALIGN, CSn_START, CLK_SETUP, CLK_HOLD, CSn_END );
106
  signal spi_state           : SPI_STATES;
107
 
108
  signal spi_wr_buffer       : std_logic_vector(15 downto 0) := x"0000";
109
  signal spi_rd_buffer       : std_logic_vector(15 downto 0) := x"0000";
110
 
111
  signal bit_cntr            : std_logic_vector(3 downto 0) := x"0";
112
 
113
begin
114
 
115
  ADC_Control_FSM_proc: process( Clock, Reset )
116
  begin
117
    if( Reset = Reset_Level )then
118
      ADC_State              <= INIT;
119
      Channel                <= (others => '0');
120
      Conv_Start             <= '0';
121
 
122
      RAW_Channel            <= (others => '0');
123
      RAW_Data               <= (others => '0');
124
      RAW_Valid              <= '0';
125
 
126
    elsif( rising_edge(Clock) )then
127
      Conv_Start             <= '0';
128
 
129
      RAW_Channel            <= (others => '0');
130
      RAW_Data               <= (others => '0');
131
      RAW_Valid              <= '0';
132
 
133
      case ADC_State is
134
        when INIT =>
135
          Channel            <= (others => '0');
136
          ADC_State          <= IDLE;
137
 
138
        when IDLE =>
139
          if( Reinit = '1' )then
140
            ADC_State        <= INIT;
141
          elsif( Busy_In = '0' )then
142
            ADC_State        <= REQ_SP;
143
          end if;
144
 
145
        when REQ_SP =>
146
          Conv_Start         <= '1';
147
          ADC_State          <= SP_WAIT;
148
 
149
        when SP_WAIT =>
150
          if( Valid = '1' )then
151 319 jshamlet
            RAW_Channel      <= Channel - 1;
152 315 jshamlet
            RAW_Data         <= "0000" & Data_Out;
153
            RAW_Valid        <= '1';
154
            ADC_State        <= INC_CH;
155
          end if;
156
 
157
        when INC_CH =>
158
          Channel            <= Channel + 1;
159
          ADC_State          <= IDLE;
160
 
161
        when others =>
162
          null;
163
      end case;
164
    end if;
165
  end process;
166
 
167
 
168
  SPI_IO_FSM: process( Clock, Reset )
169
  begin
170
    if( Reset = Reset_Level )then
171
      spi_state              <= IDLE;
172
      spi_wr_buffer          <= (others => '0');
173
      spi_rd_buffer          <= (others => '0');
174
      bit_cntr               <= (others => '0');
175
 
176
 
177
      HT_Cntr                <= (others => '0');
178
      HT_Tick                <= '0';
179
 
180
      SDI                    <= '0';
181
      SCLK                   <= '0';
182
      CSn                    <= '1';
183
 
184
      Data_Out               <= (others => '0');
185
      Valid                  <= '0';
186
    elsif( rising_edge(Clock) )then
187
 
188
      HT_Cntr                <= HT_Cntr - 1;
189
      HT_Tick                <= '0';
190
      if( HT_Cntr = 0 )then
191
        HT_Cntr              <= CLK_DIV_VAL;
192
        HT_Tick              <= '1';
193
      end if;
194
 
195
      SCLK                   <= '1';
196
      SDI                    <= '1';
197
 
198
      Valid                  <= '0';
199
 
200
      case( spi_state )is
201
        when IDLE =>
202
          CSn                <= '1';
203
          bit_cntr           <= x"F";
204
          if( Conv_Start = '1' )then
205
            spi_wr_buffer    <= "00" & Channel & "00000000000";
206
            spi_state        <= ALIGN;
207
          end if;
208
 
209
        when ALIGN =>
210
          if( HT_Tick = '1' )then
211
            spi_state        <= CSn_START;
212
          end if;
213
 
214
        when CSn_START =>
215
          CSn                <= '0';
216
          if( HT_Tick = '1' )then
217
            spi_state        <= CLK_SETUP;
218
          end if;
219
 
220
        when CLK_SETUP =>
221
          SCLK               <= '0';
222
          SDI                <= spi_wr_buffer(conv_integer(bit_cntr));
223
          CSn                <= '0';
224
          if( HT_Tick = '1' )then
225
            spi_rd_buffer    <= spi_rd_buffer(14 downto 0) & SDO;
226
            spi_state        <= CLK_HOLD;
227
          end if;
228
 
229
        when CLK_HOLD =>
230
          SDI                <= spi_wr_buffer(conv_integer(bit_cntr));
231
          if( HT_Tick = '1' )then
232
            bit_cntr         <= bit_cntr - 1;
233
            spi_state        <= CLK_SETUP;
234
            if( bit_cntr = 0 )then
235
              spi_state      <= CSn_END;
236
            end if;
237
          end if;
238
 
239
        when CSn_END =>
240
          if( HT_Tick = '1' )then
241
            Data_Out         <= spi_rd_buffer(11 downto 0);
242
            Valid            <= '1';
243
            spi_state        <= IDLE;
244
          end if;
245
 
246
        when others =>
247
          null;
248
      end case;
249
 
250
    end if;
251
  end process;
252
 
253
end architecture;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.