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

Subversion Repositories etherlab

[/] [etherlab/] [trunk/] [vhdl/] [io.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 idiolatrie
--------------------------------------------------------------------------------
2
-- ETHERLAB - FPGA To C# To LABVIEW Bridge                                    --
3
--------------------------------------------------------------------------------
4
-- REFERNCES                                                                  --
5
--  [1] LTC2604/LTC2614/LTC2624 Quad 16-Bit Rail-to-Rail DACs                 --
6
--  [2] Xilinx UG230                                                          --
7
--  [3] LTC6912 Dual Programmable Gain Amplifiers                             --
8
--  [4] LTC1407/LTC1407A Serial 12-Bit/14-Bit, 3Msps ADCs                     --
9
--------------------------------------------------------------------------------
10
-- Copyright (C)2012  Mathias Hörtnagl <mathias.hoertnagl@gmail.com>          --
11
--                                                                            --
12
-- This program is free software: you can redistribute it and/or modify       --
13
-- it under the terms of the GNU General Public License as published by       --
14
-- the Free Software Foundation, either version 3 of the License, or          --
15
-- (at your option) any later version.                                        --
16
--                                                                            --
17
-- This program is distributed in the hope that it will be useful,            --
18
-- but WITHOUT ANY WARRANTY; without even the implied warranty of             --
19
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              --
20
-- GNU General Public License for more details.                               --
21
--                                                                            --
22
-- You should have received a copy of the GNU General Public License          --
23
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.      --
24
--------------------------------------------------------------------------------
25
library ieee;
26
use ieee.std_logic_1164.all;
27
use ieee.numeric_std.all;
28
 
29
library work;
30
use work.common.all;
31
 
32
entity io is
33
   port(
34
      clk         : in  std_logic;
35
      clk90       : in  std_logic;
36
   -- EtherLab data received.
37
      el_chnl     : in  std_logic_vector(7 downto 0);
38
      el_data     : in  data_t;
39
      el_dv       : in  std_logic;
40
      el_ack      : out std_logic;
41
   -- EtherLab data to send.
42
      el_snd_chnl : out std_logic_vector(7 downto 0);
43
      el_snd_data : out data_t;
44
      el_snd_en   : out std_logic;
45
   -- DAC/ADC Connections.
46
      SPI_MISO    : in  std_logic;
47
      SPI_MOSI    : out std_logic;
48
      SPI_SCK     : out std_logic;
49
      DAC_CS      : out std_logic;
50
      DAC_CLR     : out std_logic;
51
      AD_CONV     : out std_logic;
52
      AMP_CS      : out std_logic;
53
   -- Digital lines.
54
      DI          : in  std_logic_vector(3 downto 0);
55
      DO          : out std_logic_vector(3 downto 0);
56
   -- SWITCHES.
57
      SW          : in  std_logic_vector(3 downto 0);
58
   -- BUTTONS.
59
      BTN         : in  std_logic_vector(3 downto 0);
60
   -- LEDs.
61
      LED         : out std_logic_vector(7 downto 0)
62
   );
63
end io;
64
 
65
architecture rtl of io is
66
 
67
   -----------------------------------------------------------------------------
68
   -- SETTING:                                                                --
69
   --  + FREQ: Clock frequency. Usually 50 MHz.                               --
70
   --  + PULSE_WIDTH: Time between two EtherLab transmissions.                --   
71
   -----------------------------------------------------------------------------
72
   constant FREQ        : natural := 50;     -- [MHz] Frequency.
73
   constant PULSE_WIDTH : natural := 100;    -- [msec] Time between two sends.
74
 
75
   constant CYCLES_PER_MSEC : natural := 1000000/FREQ;
76
 
77
   type state_t is (Idle, Ready, AnalogOut, Send);
78
 
79
   type reg_t is record
80
      s    : state_t;
81
      chnl : std_logic_vector(7 downto 0);      -- Channel latch.
82
      ao   : std_logic_vector(23 downto 4);     -- Analog out register.
83
      do   : std_logic_vector(3 downto 0);      -- Digital out register.
84
      led  : std_logic_vector(7 downto 0);      -- LED register.
85
      c    : natural range 0 to 23;
86
   end record;
87
 
88
   type snd_state_t is (Idle, Pulse, Transmit);
89
 
90
   type snd_t is record
91
      s : snd_state_t;
92
      d : data_t;                                  -- EtherLab data struct.
93
      q : natural range 0 to CYCLES_PER_MSEC-1;    -- Milliseconds counter.
94
      p : natural range 0 to PULSE_WIDTH-1;        -- Pulse counter.
95
   end record;
96
 
97
   signal r, rin : reg_t := reg_t'(Idle, x"00", x"00000", x"0", x"00", 0);
98
   signal s, sin : snd_t := snd_t'(Idle, (others => (others => '0')), 0,0);
99
begin
100
 
101
   snd : process(s, SW, BTN)
102
   begin
103
 
104
      sin <= s;
105
 
106
      el_snd_en <= '0';                   -- Turn off Ethernet packet sending.
107
 
108
      case s.s is
109
 
110
         when Idle =>
111
            if s.q = (CYCLES_PER_MSEC-1) then
112
               sin.q <= 0;
113
               if s.p = (PULSE_WIDTH-1) then
114
                  sin.p <= 0;
115
                  sin.s <= Pulse;
116
               else
117
                  sin.p <= s.p + 1;
118
               end if;
119
            else
120
               sin.q <= s.q + 1;
121
            end if;
122
 
123
         when Pulse =>
124
            sin.d(CHANNEL_E) <= x"000" & DI;       -- Sample digital input.
125
            sin.d(CHANNEL_G) <= x"000" & BTN;      -- Sample buttons.
126
            sin.d(CHANNEL_H) <= x"000" & SW;       -- Sample switches.
127
            sin.s            <= Transmit;
128
 
129
         when Transmit =>
130
            el_snd_en <= '1';                      -- Send Ethernet packet.
131
            sin.s     <= Idle;
132
 
133
      end case;
134
   end process;
135
 
136
   el_snd_chnl <= "11010000";
137
   el_snd_data <= s.d;
138
 
139
 
140
   nsl : process(r, el_chnl, el_data, el_dv, clk90, SPI_MISO)
141
 
142
      -- DAC Commands and Addresses.
143
      constant CMD_UP : std_logic_vector(3 downto 0) := "0011";
144
      constant ADR_OA : std_logic_vector(3 downto 0) := "0000";
145
      constant ADR_OB : std_logic_vector(3 downto 0) := "0001";
146
      constant ADR_OC : std_logic_vector(3 downto 0) := "0010";
147
      constant ADR_OD : std_logic_vector(3 downto 0) := "0011";
148
   begin
149
 
150
      rin <= r;
151
 
152
      SPI_MOSI <= r.ao(23);      -- Send always the MSBit of the data register.
153
      SPI_SCK  <= '0';           -- Pull down SPI clock.
154
      DAC_CLR  <= '1';           -- Disable D/A Converter.
155
      DAC_CS   <= '1';
156
      AD_CONV  <= '0';           -- Disable A/D Converter.
157
      AMP_CS   <= '1';           -- Disable Pre Amplifier.
158
 
159
      el_ack    <= '0';          -- Ethernet receiver data ready ACK.
160
 
161
      case r.s is
162
         when Idle =>
163
            if el_dv = '1' then
164
               rin.chnl <= el_chnl;
165
               rin.s <= Ready;
166
            end if;
167
 
168
         -- IMPROVE: Merge Ready and AnalogOut states.
169
         when Ready =>
170
            --------------------------------------------------------------------
171
            -- LED Control                                                    --
172
            --------------------------------------------------------------------
173
            if isSet(r.chnl, CHANNEL_H) then
174
               rin.led <= el_data(CHANNEL_H)(7 downto 0);
175
               rin.chnl(CHANNEL_H) <= '0';
176
            end if;
177
            --------------------------------------------------------------------
178
            -- Digital Out Control                                            --
179
            --------------------------------------------------------------------
180
            if isSet(r.chnl, CHANNEL_G) then
181
               rin.do <= el_data(CHANNEL_G)(3 downto 0);
182
               rin.chnl(CHANNEL_G) <= '0';
183
            end if;
184
            --------------------------------------------------------------------
185
            -- Analog Out Control                                             --
186
            --------------------------------------------------------------------
187
            if r.chnl(3 downto 0) /= x"0" then
188
               rin.s <= AnalogOut;
189
            else
190
               rin.s <= Idle;
191
            end if;
192
 
193
         -----------------------------------------------------------------------
194
         -- Analog Out Control                                                --
195
         -----------------------------------------------------------------------
196
         -- Send data to DAC. Since all DACs are controlled via a singe serial 
197
         -- interface, the setting of new data follows the following precedence:
198
         -- A > B > C > D. Thus if data is ready for analog output A, it will be
199
         -- sent first. Next is analog output B, then C and finally D. 
200
         when AnalogOut =>
201
            if isSet(r.chnl, CHANNEL_A) then
202
               rin.ao <= CMD_UP & ADR_OA & el_data(CHANNEL_A)(11 downto 0);
203
               rin.chnl(CHANNEL_A) <= '0';   -- Clear channel flag.
204
               rin.s <= Send;
205
            elsif isSet(r.chnl, CHANNEL_B) then
206
               rin.ao <= CMD_UP & ADR_OB & el_data(CHANNEL_B)(11 downto 0);
207
               rin.chnl(CHANNEL_B) <= '0';
208
               rin.s <= Send;
209
            elsif isSet(r.chnl, CHANNEL_C) then
210
               rin.ao <= CMD_UP & ADR_OC & el_data(CHANNEL_C)(11 downto 0);
211
               rin.chnl(CHANNEL_C) <= '0';
212
               rin.s <= Send;
213
            elsif isSet(r.chnl, CHANNEL_D) then
214
               rin.ao <= CMD_UP & ADR_OD & el_data(CHANNEL_D)(11 downto 0);
215
               rin.chnl(CHANNEL_D) <= '0';
216
               rin.s <= Send;
217
            else
218
               rin.s <= Idle;    -- All flags are cleared and DACs are updated.
219
            end if;
220
 
221
         -- To send data at maximum speed, we send clk90, wich is the clock
222
         -- signal phase shifted by 90 degree. This is necessary to meet the
223
         -- timing constraints t1 and t2 defined in [1].
224
         when Send =>
225
            DAC_CS  <= '0';
226
            SPI_SCK <= clk90;
227
            rin.ao  <= r.ao(22 downto 4) & '0';
228
            if r.c = 23 then
229
               rin.c <= 0;
230
               rin.s <= AnalogOut;
231
            else
232
               rin.c <= r.c + 1;
233
               rin.s <= Send;
234
            end if;
235
 
236
         -----------------------------------------------------------------------
237
         -- TODO: Analog In Control                                           --
238
         -----------------------------------------------------------------------
239
         -- Pulse the ADC and capture the data from the last pulse.
240
         -- when Pulse =>
241
            -- AD_CONV <= '1';
242
            -- SPI_SCK <= clk90;
243
            -- rin.c   <= 0;
244
            -- rin.d(CHANNEL_E) <= x"000" & DI;       -- Sample digital input.
245
            -- rin.d(CHANNEL_G) <= x"000" & BTN;      -- Sample buttons.
246
            -- rin.d(CHANNEL_H) <= x"000" & SW;       -- Sample switches.
247
            -- rin.s   <= Transmit; --Wait0;
248
 
249
         -- when Wait0 =>
250
            -- SPI_SCK <= clk90;
251
            -- if r.c = 1 then
252
               -- rin.c <= 0;
253
               -- rin.s <= Receive0;
254
            -- else
255
               -- rin.c <= r.c + 1;
256
            -- end if;            
257
 
258
         -- when Receive0 =>
259
            -- SPI_SCK <= clk90;
260
            -- rin.d(CHANNEL_A) <= r.d(CHANNEL_A)(15 downto 1) & SPI_MISO;
261
            -- if r.c = 13 then
262
               -- rin.c <= 0;
263
               -- rin.s <= Wait1;
264
            -- else
265
               -- rin.c <= r.c + 1;
266
            -- end if;
267
 
268
         -- when Wait1 =>
269
            -- SPI_SCK <= clk90;
270
            -- if r.c = 1 then
271
               -- rin.c <= 0;
272
               -- rin.s <= Receive1;
273
            -- else
274
               -- rin.c <= r.c + 1;
275
            -- end if;            
276
 
277
         -- when Receive1 =>
278
            -- SPI_SCK <= clk90;
279
            -- rin.d(CHANNEL_B) <= r.d(CHANNEL_B)(15 downto 1) & SPI_MISO;
280
            -- if r.c = 13 then
281
               -- rin.c <= 0;
282
               -- rin.s <= Transmit;
283
            -- else
284
               -- rin.c <= r.c + 1;
285
            -- end if;
286
 
287
      end case;
288
   end process;
289
 
290
   DO  <= r.do;
291
   LED <= r.led;
292
 
293
   reg : process(clk)
294
   begin
295
      if rising_edge(clk) then
296
         r <= rin;
297
         s <= sin;
298
      end if;
299
   end process;
300
end rtl;

powered by: WebSVN 2.1.0

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