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

Subversion Repositories pmodda4driver

[/] [pmodda4driver/] [trunk/] [hw/] [sources/] [PmodDA4Driver.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ldalmasso
------------------------------------------------------------------------
2
-- Engineer:    Dalmasso Loic
3
-- Create Date: 05/02/2025
4
-- Module Name: PmodDA4Driver
5
-- Description:
6
--      Pmod DA4 Driver for the 8 Channels 12-bit Digital-to-Analog Converter AD5628. The communication with the DAC uses the SPI protocol (Write only)
7
--      User can specifies the SPI Serial Clock Frequency (up to 50 MHz).
8
--
9
-- Usage:
10
--              The o_ready signal (set to '1') indicates the PmodDA4Driver is ready to receive new data (command, address and digital value).
11
--              Once data are set, the i_enable signal can be triggered (set to '1') to begin transmission.
12
--              The o_ready signal is set to '0' to acknowledge the receipt and the application of the new data.
13
--              When the transmission is complete, the o_ready is set to '1' and the PmodDA4Driver is ready for new transmission.
14
--
15
--      Commands
16
--      | C3 | C2 | C1 | C0 | Description
17
--      |  0 |  0 |  0 |  0 | Write to Input Register n
18
--      |  0 |  0 |  0 |  1 | Update DAC Register n
19
--      |  0 |  0 |  1 |  0 | Write to Input Register n, update all (software /LDAC)
20
--      |  0 |  0 |  1 |  1 | Write to and update DAC Channel n
21
--      |  0 |  1 |  0 |  0 | Power down/power up DAC
22
--      |  0 |  1 |  0 |  1 | Load clear code register
23
--      |  0 |  1 |  1 |  0 | Load /LDAC register
24
--      |  0 |  1 |  1 |  1 | Reset (power-on reset)
25
--      |  1 |  0 |  0 |  0 | Set up internal REF register
26
--      |  - |  - |  - |  - | Reserved
27
--
28
--      Address
29
--      | A3 | A2 | A1 | A0 | Description
30
--      |  0 |  0 |  0 |  0 | DAC Channel A
31
--      |  0 |  0 |  0 |  1 | DAC Channel B
32
--      |  0 |  0 |  1 |  0 | DAC Channel C
33
--      |  0 |  0 |  1 |  1 | DAC Channel D
34
--      |  0 |  1 |  0 |  0 | DAC Channel E
35
--      |  0 |  1 |  0 |  1 | DAC Channel F
36
--      |  0 |  1 |  1 |  0 | DAC Channel G
37
--      |  0 |  1 |  1 |  1 | DAC Channel H
38
--      |  1 |  1 |  1 |  1 | DAC All Channels
39
--
40
-- Generics
41
--              sys_clock: System Input Clock Frequency (Hz)
42
--      spi_clock: SPI Serial Clock Frequency (up to 50 MHz)
43
-- Ports
44
--              Input   -       i_sys_clock: System Input Clock
45
--              Input   -       i_enable: Module Enable ('0': Disable, '1': Enable)
46
--              Input   -       i_command: DAC Command (4 bits)
47
--              Input   -       i_addr: DAC Address Register (4 bits)
48
--              Input   -       i_digital_value: Digital Value to convert (12 bits)
49
--              Input   -       i_config: DAC Configuration Bits (8 bits)
50
--              Output  -       o_ready: Ready to convert Next Digital Value ('0': NOT Ready, '1': Ready)
51
--              Output  -       o_sclk: SPI Serial Clock
52
--              Output  -       o_mosi: SPI Master Output Slave Input Data line
53
--              Output  -       o_ss: SPI Slave Select Line ('0': Enable, '1': Disable)
54
------------------------------------------------------------------------
55
 
56
LIBRARY IEEE;
57
USE IEEE.STD_LOGIC_1164.ALL;
58
USE IEEE.NUMERIC_STD.ALL;
59
 
60
ENTITY PmodDA4Driver is
61
 
62
GENERIC(
63
        sys_clock: INTEGER := 100_000_000;
64
        spi_clock: INTEGER range 1 to 50_000_000 := 1_000_000
65
);
66
 
67
PORT(
68
        i_sys_clock: IN STD_LOGIC;
69
    i_enable: IN STD_LOGIC;
70
    i_command: IN UNSIGNED(3 downto 0);
71
    i_addr: IN UNSIGNED(3 downto 0);
72
        i_digital_value: IN UNSIGNED(11 downto 0);
73
        i_config: IN UNSIGNED(7 downto 0);
74
    o_ready: OUT STD_LOGIC;
75
        o_sclk: OUT STD_LOGIC;
76
    o_mosi: OUT STD_LOGIC;
77
        o_ss: OUT STD_LOGIC
78
);
79
 
80
END PmodDA4Driver;
81
 
82
ARCHITECTURE Behavioral of PmodDA4Driver is
83
 
84
------------------------------------------------------------------------
85
-- Constant Declarations
86
------------------------------------------------------------------------
87
-- AD5628 Don't Care Bit
88
constant AD5628_DONT_CARE_BIT: STD_LOGIC := '0';
89
 
90
-- SPI Clock Dividers
91
constant CLOCK_DIV: INTEGER := sys_clock / spi_clock;
92
constant CLOCK_DIV_X2: INTEGER := CLOCK_DIV /2;
93
 
94
-- SPI SCLK IDLE Bit
95
constant SCLK_IDLE_BIT: STD_LOGIC := '0';
96
 
97
-- SPI MOSI IDLE Bit
98
constant MOSI_IDLE_BIT: STD_LOGIC := '0';
99
 
100
-- SPI Enable Slave Select Line
101
constant ENABLE_SS_LINE: STD_LOGIC := '0';
102
 
103
------------------------------------------------------------------------
104
-- Signal Declarations
105
------------------------------------------------------------------------
106
-- Pmod DA4 Input Registers
107
signal enable_reg: STD_LOGIC := '0';
108
signal command_reg: UNSIGNED(3 downto 0) := (others => '0');
109
signal addr_reg: UNSIGNED(3 downto 0) := (others => '0');
110
signal digital_value_reg: UNSIGNED(11 downto 0) := (others => '0');
111
signal config_reg: UNSIGNED(7 downto 0) := (others => '0');
112
 
113
-- SPI Master States
114
TYPE spiState is (IDLE, BYTES_TX, WAITING);
115
signal state: spiState := IDLE;
116
signal next_state: spiState;
117
 
118
-- SPI Clock Divider
119
signal spi_clock_divider: INTEGER range 0 to CLOCK_DIV-1 := 0;
120
signal spi_clock_rising: STD_LOGIC := '0';
121
signal spi_clock_falling: STD_LOGIC := '0';
122
 
123
-- SPI Transmission Bit Counter (31 bits)
124
signal bit_counter: UNSIGNED(4 downto 0) := (others => '0');
125
signal bit_counter_end: STD_LOGIC := '0';
126
 
127
-- SPI SCLK
128
signal sclk_out: STD_LOGIC := '0';
129
 
130
-- SPI MOSI Register
131
signal mosi_reg: UNSIGNED(31 downto 0) := (others => '0');
132
 
133
------------------------------------------------------------------------
134
-- Module Implementation
135
------------------------------------------------------------------------
136
begin
137
 
138
        ------------------------------
139
        -- Pmod DA4 Input Registers --
140
        ------------------------------
141
        process(i_sys_clock)
142
        begin
143
 
144
                if rising_edge(i_sys_clock) then
145
 
146
            -- Load Inputs
147
            if (state = IDLE) then
148
                                enable_reg <= i_enable;
149
                command_reg <= i_command;
150
                addr_reg <= i_addr;
151
                digital_value_reg <= i_digital_value;
152
                                config_reg <= i_config;
153
            end if;
154
 
155
        end if;
156
    end process;
157
 
158
        -----------------------
159
        -- SPI Clock Divider --
160
        -----------------------
161
        process(i_sys_clock)
162
        begin
163
                if rising_edge(i_sys_clock) then
164
 
165
                        -- Reset SPI Clock Divider
166
                        if (enable_reg = '0') or (spi_clock_divider = CLOCK_DIV-1) then
167
                                spi_clock_divider <= 0;
168
 
169
                        -- Increment SPI Clock Divider
170
                        else
171
                spi_clock_divider <= spi_clock_divider +1;
172
                        end if;
173
                end if;
174
        end process;
175
 
176
        ---------------------
177
        -- SPI Clock Edges --
178
        ---------------------
179
        process(i_sys_clock)
180
        begin
181
                if rising_edge(i_sys_clock) then
182
 
183
                        -- SPI Clock Rising Edge
184
                        if (spi_clock_divider = CLOCK_DIV-1) then
185
                                spi_clock_rising <= '1';
186
                        else
187
                                spi_clock_rising <= '0';
188
                        end if;
189
 
190
                        -- SPI Clock Falling Edge
191
                        if (spi_clock_divider = CLOCK_DIV_X2-1) then
192
                                spi_clock_falling <= '1';
193
                        else
194
                                spi_clock_falling <= '0';
195
                        end if;
196
 
197
                end if;
198
        end process;
199
 
200
        -----------------------
201
        -- SPI State Machine --
202
        -----------------------
203
    -- SPI State
204
        process(i_sys_clock)
205
        begin
206
                if rising_edge(i_sys_clock) then
207
 
208
                        -- Next State (When SPI Clock Rising Edge)
209
                        if (spi_clock_rising = '1') then
210
                                state <= next_state;
211
                        end if;
212
 
213
                end if;
214
        end process;
215
 
216
        -- SPI Next State
217
        process(state, enable_reg, bit_counter_end)
218
        begin
219
                case state is
220
                        when IDLE =>    if (enable_reg = '1') then
221
                                next_state <= BYTES_TX;
222
                            else
223
                                next_state <= IDLE;
224
                                                        end if;
225
 
226
                        -- Bytes TX Cycle
227
                        when BYTES_TX =>
228
                                                        -- End of Bytes TX Cycle
229
                                                        if (bit_counter_end = '1') then
230
                                next_state <= WAITING;
231
                                                        else
232
                                                                next_state <= BYTES_TX;
233
                                                        end if;
234
 
235
            -- Waiting Time for Next Transmission
236
                        when others => next_state <= IDLE;
237
                end case;
238
        end process;
239
 
240
        ---------------------
241
        -- SPI Bit Counter --
242
        ---------------------
243
        process(i_sys_clock)
244
        begin
245
                if rising_edge(i_sys_clock) then
246
 
247
                        -- SPI Clock Rising Edge
248
                        if (spi_clock_rising = '1') then
249
 
250
                -- Increment Bit Counter
251
                if (state = BYTES_TX) then
252
                    bit_counter <= bit_counter +1;
253
 
254
                -- Reset Bit Counter
255
                                else
256
                                        bit_counter <= (others => '0');
257
                                end if;
258
                        end if;
259
                end if;
260
    end process;
261
 
262
        -- Bit Counter End
263
        bit_counter_end <= bit_counter(4) and bit_counter(3) and bit_counter(2) and bit_counter(1) and bit_counter(0);
264
 
265
        --------------------
266
        -- Pmod DA4 Ready --
267
        --------------------
268
    o_ready <= '1' when (state = IDLE) else '0';
269
 
270
    ---------------------
271
        -- SPI SCLK Output --
272
        ---------------------
273
        process(i_sys_clock)
274
        begin
275
                if rising_edge(i_sys_clock) then
276
 
277
                        -- SCLK Rising Edge
278
                        if (spi_clock_rising = '1') then
279
                                sclk_out <= '1';
280
 
281
                        -- SCLK Falling Edge
282
                        elsif (spi_clock_falling = '1') then
283
                sclk_out <= '0';
284
 
285
                        end if;
286
                end if;
287
        end process;
288
        o_sclk <= sclk_out when state = BYTES_TX else SCLK_IDLE_BIT;
289
 
290
        ----------------------------
291
        -- SPI Write Value (MOSI) --
292
        ----------------------------
293
        process(i_sys_clock)
294
        begin
295
 
296
                if rising_edge(i_sys_clock) then
297
 
298
                        -- Load MOSI Register
299
                        if (state = IDLE) then
300
 
301
                -- Don't Care Bits
302
                                mosi_reg(31 downto 28) <= (others => AD5628_DONT_CARE_BIT);
303
 
304
                -- Command Bits
305
                mosi_reg(27 downto 24) <= command_reg;
306
 
307
                -- Address Bits
308
                mosi_reg(23 downto 20) <= addr_reg;
309
 
310
                -- Data Bits
311
                mosi_reg(19 downto 8) <= digital_value_reg;
312
 
313
                -- Configuration Bits
314
                                mosi_reg(7 downto 0) <= config_reg;
315
 
316
                        -- Left-Shift MOSI Register 
317
                        elsif (state = BYTES_TX) and (spi_clock_rising = '1') then
318
                                mosi_reg <= mosi_reg(30 downto 0) & MOSI_IDLE_BIT;
319
                        end if;
320
 
321
                end if;
322
        end process;
323
        o_mosi <= mosi_reg(31) when state = BYTES_TX else MOSI_IDLE_BIT;
324
 
325
    ---------------------------
326
        -- SPI Slave Select Line --
327
        ---------------------------
328
    o_ss <= ENABLE_SS_LINE when state = BYTES_TX else not(ENABLE_SS_LINE);
329
 
330
end Behavioral;

powered by: WebSVN 2.1.0

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