1 |
2 |
ldalmasso |
------------------------------------------------------------------------
|
2 |
|
|
-- Engineer: Dalmasso Loic
|
3 |
|
|
-- Create Date: 07/02/2025
|
4 |
|
|
-- Module Name: PmodAD2Driver
|
5 |
|
|
-- Description:
|
6 |
|
|
-- Pmod AD2 Driver for the 4 Channels of 12-bit Analog-to-Digital Converter AD7991. The communication with the ADC uses the I2C protocol.
|
7 |
|
|
-- User can specifies the I2C Clock Frequency (up to 400 kHz with the Fast Mode).
|
8 |
|
|
--
|
9 |
|
|
-- WARNING: /!\ Require Pull-Up on SCL and SDA pins /!\
|
10 |
|
|
--
|
11 |
|
|
-- Usage:
|
12 |
|
|
-- User specifies inputs: I2C mode (i_mode), ADC Slave Address (i_addr), Configuration Byte (i_config_byte, write mode only) and the Last Read Cycle trigger (i_last_read, read mode only)
|
13 |
|
|
-- The transmission begin when the i_enable signal is set to '1'.
|
14 |
|
|
-- When started, the PmodAD2Driver executes the complete operation cycle (configurations or ADC conversions) independently of the new i_enable signal value (the i_enable signal can be reset).
|
15 |
|
|
-- At the end of the operation cycle, if the i_enable signal is still set to '1', the PmodAD2Driver executes the operation again with the current inputs.
|
16 |
|
|
-- The o_ready signal (set to '1') indicates the PmodAD2Driver is ready to process new operation. The o_ready signal is set to '0' to acknowledge the receipt.
|
17 |
|
|
-- The o_ready signal is set to '0' to acknowledge the receipt.
|
18 |
|
|
-- In Write mode, the PmodAD2Driver writes the Configuration byte into the ADC register and stop the transmission.
|
19 |
|
|
-- In Read mode, the PmodAD2Driver always reads 2-byte ADC conversion values channel-by-channel (according to ADC configuration).
|
20 |
|
|
-- The ADC value (o_adc_value) is available when its validity signal (o_adc_valid) is asserted.
|
21 |
|
|
-- In Read mode, while the i_last_read is NOT set to '1', the PmodAD2Driver execute the 2-byte ADC conversion value.
|
22 |
|
|
-- When the i_last_read is set to '1', the PmodAD2Driver ends the 2-byte ADC conversion value and return to IDLE state, and waits for the i_enable signal is set to '1'.
|
23 |
|
|
--
|
24 |
|
|
-- ADC AD7991 has 2 I2C Addresses:
|
25 |
|
|
-- AD7991-0: 010 1000
|
26 |
|
|
-- AD7991-1: 010 1001
|
27 |
|
|
--
|
28 |
|
|
-- Configuration Register (8-bit Write Only)
|
29 |
|
|
-- | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Bit
|
30 |
|
|
-- | CH3 | CH2 | CH1 | CH0 | REF_SEL | FLTR | Bit Trial delay | Sample delay | Description
|
31 |
|
|
-- | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | Default Value
|
32 |
|
|
--
|
33 |
|
|
-- Configuration Register MSB Description
|
34 |
|
|
-- | D7 | D6 | D5 | D4 | Analog Input Channel
|
35 |
|
|
-- | 0 | 0 | 0 | 0 | No channel selected
|
36 |
|
|
-- | 0 | 0 | 0 | 1 | Convert on VIN0
|
37 |
|
|
-- | 0 | 0 | 1 | 0 | Convert on VIN1
|
38 |
|
|
-- | 0 | 0 | 1 | 1 | Sequence between VIN0 and VIN1
|
39 |
|
|
-- | 0 | 1 | 0 | 0 | Convert on VIN2
|
40 |
|
|
-- | 0 | 1 | 0 | 1 | Sequence between VIN0 and VIN2
|
41 |
|
|
-- | 0 | 1 | 1 | 0 | Sequence between VIN1 and VIN2
|
42 |
|
|
-- | 0 | 1 | 1 | 1 | Sequence among VIN0, VIN1, and VIN2
|
43 |
|
|
-- | 1 | 0 | 0 | 0 | Convert on VIN3
|
44 |
|
|
-- | 1 | 0 | 0 | 1 | Sequence between VIN0 and VIN3
|
45 |
|
|
-- | 1 | 0 | 1 | 0 | Sequence between VIN1 and VIN3
|
46 |
|
|
-- | 1 | 0 | 1 | 1 | Sequence among VIN0, VIN1, and VIN3
|
47 |
|
|
-- | 1 | 1 | 0 | 0 | Sequence between VIN2 and VIN3
|
48 |
|
|
-- | 1 | 1 | 0 | 1 | Sequence among VIN0, VIN2, and VIN3
|
49 |
|
|
-- | 1 | 1 | 1 | 0 | Sequence among VIN1, VIN2, and VIN3
|
50 |
|
|
-- | 1 | 1 | 1 | 1 | Sequence among VIN0, VIN1, VIN2, and VIN3
|
51 |
|
|
--
|
52 |
|
|
-- Conversion Result Register (16-bit Read Only)
|
53 |
|
|
-- | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
54 |
|
|
-- | 0 | 0 | CHID1 | CHID0 | MSB | B10 | B9 | B8 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
|
55 |
|
|
--
|
56 |
|
|
-- Generics
|
57 |
|
|
-- sys_clock: System Input Clock Frequency (Hz)
|
58 |
|
|
-- i2c_clock: I2C Serial Clock Frequency (Standard Mode: 100 kHz, Fast Mode: 400 kHz)
|
59 |
|
|
-- Ports
|
60 |
|
|
-- Input - i_sys_clock: System Input Clock
|
61 |
|
|
-- Input - i_enable: Module Enable ('0': Disable, '1': Enable)
|
62 |
|
|
-- Input - i_mode: Read or Write Mode ('0': Write, '1': Read)
|
63 |
|
|
-- Input - i_addr: ADC Address (7 bits)
|
64 |
|
|
-- Input - i_config_byte: ADC Configuration Byte (8 bits)
|
65 |
|
|
-- Input - i_last_read: Indicates the Last Read Operation ('0': Continue Read Cycle, '1': Last Read Cycle)
|
66 |
|
|
-- Output - o_adc_valid: ADC Read Value Valid ('0': Not Valid, '1': Valid)
|
67 |
|
|
-- Output - o_adc_value: ADC Read Value
|
68 |
|
|
-- Output - o_ready: ADC Ready Status ('0': NOT Ready, '1': Ready)
|
69 |
|
|
-- In/Out - io_scl: I2C Serial Clock ('0'-'Z'(as '1') values, working with Pull-Up)
|
70 |
|
|
-- In/Out - io_sda: I2C Serial Data ('0'-'Z'(as '1') values, working with Pull-Up)
|
71 |
|
|
------------------------------------------------------------------------
|
72 |
|
|
|
73 |
|
|
LIBRARY IEEE;
|
74 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
75 |
|
|
USE IEEE.NUMERIC_STD.ALL;
|
76 |
|
|
|
77 |
|
|
ENTITY Testbench_PmodAD2Driver is
|
78 |
|
|
-- Port ( );
|
79 |
|
|
END Testbench_PmodAD2Driver;
|
80 |
|
|
|
81 |
|
|
ARCHITECTURE Behavioral of Testbench_PmodAD2Driver is
|
82 |
|
|
|
83 |
|
|
COMPONENT PmodAD2Driver is
|
84 |
|
|
|
85 |
|
|
GENERIC(
|
86 |
|
|
sys_clock: INTEGER := 100_000_000;
|
87 |
|
|
i2c_clock: INTEGER range 1 to 400_000 := 100_000
|
88 |
|
|
);
|
89 |
|
|
|
90 |
|
|
PORT(
|
91 |
|
|
i_sys_clock: IN STD_LOGIC;
|
92 |
|
|
i_enable: IN STD_LOGIC;
|
93 |
|
|
i_mode: IN STD_LOGIC;
|
94 |
|
|
i_addr: IN UNSIGNED(6 downto 0);
|
95 |
|
|
i_config_byte: IN UNSIGNED(7 downto 0);
|
96 |
|
|
i_last_read: IN STD_LOGIC;
|
97 |
|
|
o_adc_valid: OUT STD_LOGIC;
|
98 |
|
|
o_adc_value: OUT UNSIGNED(15 downto 0);
|
99 |
|
|
o_ready: OUT STD_LOGIC;
|
100 |
|
|
io_scl: INOUT STD_LOGIC;
|
101 |
|
|
io_sda: INOUT STD_LOGIC
|
102 |
|
|
);
|
103 |
|
|
|
104 |
|
|
END COMPONENT;
|
105 |
|
|
|
106 |
|
|
signal sys_clock: STD_LOGIC := '0';
|
107 |
|
|
signal enable: STD_LOGIC := '0';
|
108 |
|
|
signal mode: STD_LOGIC := '0';
|
109 |
|
|
signal addr: UNSIGNED(6 downto 0):= (others => '0');
|
110 |
|
|
signal config_byte: UNSIGNED(7 downto 0):= (others => '0');
|
111 |
|
|
signal last_read: STD_LOGIC := '0';
|
112 |
|
|
signal adc_valid: STD_LOGIC := '0';
|
113 |
|
|
signal adc_value: UNSIGNED(15 downto 0):= (others => '0');
|
114 |
|
|
signal ready: STD_LOGIC := '0';
|
115 |
|
|
signal scl: STD_LOGIC := '0';
|
116 |
|
|
signal sda: STD_LOGIC := '0';
|
117 |
|
|
|
118 |
|
|
begin
|
119 |
|
|
|
120 |
|
|
-- Clock 100 MHz
|
121 |
|
|
sys_clock <= not(sys_clock) after 5 ns;
|
122 |
|
|
|
123 |
|
|
-- Enable
|
124 |
|
|
enable <= '0', '1' after 11 us, '0' after 100 us, '1' after 530 us, '0' after 630 us;
|
125 |
|
|
|
126 |
|
|
-- Mode
|
127 |
|
|
mode <= '1', -- Read
|
128 |
|
|
'0' after 509 us; -- Write
|
129 |
|
|
|
130 |
|
|
-- Address
|
131 |
|
|
addr <= "0101000", "0101001" after 300 us;
|
132 |
|
|
|
133 |
|
|
-- Config Byte
|
134 |
|
|
config_byte <= x"10";
|
135 |
|
|
|
136 |
|
|
-- Last Read
|
137 |
|
|
last_read <= '0', '1' after 351.5 us;
|
138 |
|
|
|
139 |
|
|
-- SCL
|
140 |
|
|
scl <= '1' when ready = '1' else 'Z';
|
141 |
|
|
|
142 |
|
|
-- SDA
|
143 |
|
|
sda <= 'Z',
|
144 |
|
|
-- Write Slave Address ACK
|
145 |
|
|
'0' after 111.015 us,
|
146 |
|
|
|
147 |
|
|
-- Read Byte 1.1 (0xD7)
|
148 |
|
|
'1' after 121.015 us,
|
149 |
|
|
'1' after 131.015 us,
|
150 |
|
|
'0' after 141.015 us,
|
151 |
|
|
'1' after 151.015 us,
|
152 |
|
|
'0' after 161.015 us,
|
153 |
|
|
'1' after 171.015 us,
|
154 |
|
|
'1' after 181.015 us,
|
155 |
|
|
'1' after 191.015 us,
|
156 |
|
|
'Z' after 201.015 us,
|
157 |
|
|
|
158 |
|
|
-- Read Byte 2.1 (0x15)
|
159 |
|
|
'0' after 211.015 us,
|
160 |
|
|
'0' after 221.015 us,
|
161 |
|
|
'0' after 231.015 us,
|
162 |
|
|
'1' after 241.015 us,
|
163 |
|
|
'0' after 251.015 us,
|
164 |
|
|
'1' after 261.015 us,
|
165 |
|
|
'0' after 271.015 us,
|
166 |
|
|
'1' after 281.015 us,
|
167 |
|
|
'Z' after 291.015 us,
|
168 |
|
|
|
169 |
|
|
-- Read Byte 1.2 (0xD0)
|
170 |
|
|
'1' after 301.015 us,
|
171 |
|
|
'1' after 311.015 us,
|
172 |
|
|
'0' after 321.015 us,
|
173 |
|
|
'1' after 331.015 us,
|
174 |
|
|
'0' after 341.015 us,
|
175 |
|
|
'0' after 351.015 us,
|
176 |
|
|
'0' after 361.015 us,
|
177 |
|
|
'0' after 371.015 us,
|
178 |
|
|
'Z' after 381.015 us,
|
179 |
|
|
|
180 |
|
|
-- Read Byte 2.2 (0x50)
|
181 |
|
|
'0' after 391.015 us,
|
182 |
|
|
'1' after 401.015 us,
|
183 |
|
|
'0' after 411.015 us,
|
184 |
|
|
'1' after 421.015 us,
|
185 |
|
|
'0' after 431.015 us,
|
186 |
|
|
'0' after 441.015 us,
|
187 |
|
|
'0' after 451.015 us,
|
188 |
|
|
'0' after 461.015 us,
|
189 |
|
|
'Z' after 471.015 us,
|
190 |
|
|
|
191 |
|
|
-- Write Slave Address ACK
|
192 |
|
|
'0' after 630.015 us,
|
193 |
|
|
'Z' after 640.015 us,
|
194 |
|
|
|
195 |
|
|
-- Write Config ACK
|
196 |
|
|
'0' after 720.015 us,
|
197 |
|
|
'Z' after 730.015 us;
|
198 |
|
|
|
199 |
|
|
uut: PmodAD2Driver
|
200 |
|
|
GENERIC map(
|
201 |
|
|
sys_clock => 100_000_000,
|
202 |
|
|
i2c_clock => 100_000
|
203 |
|
|
)
|
204 |
|
|
|
205 |
|
|
PORT map(
|
206 |
|
|
i_sys_clock => sys_clock,
|
207 |
|
|
i_enable => enable,
|
208 |
|
|
i_mode => mode,
|
209 |
|
|
i_addr => addr,
|
210 |
|
|
i_config_byte => config_byte,
|
211 |
|
|
i_last_read => last_read,
|
212 |
|
|
o_adc_valid => adc_valid,
|
213 |
|
|
o_adc_value => adc_value,
|
214 |
|
|
o_ready => ready,
|
215 |
|
|
io_scl => scl,
|
216 |
|
|
io_sda => sda);
|
217 |
|
|
|
218 |
|
|
end Behavioral;
|