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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [twi-master.vhd] - Blame information for rev 100

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 100 davidgb
--===========================================================================--
2
--
3
-- SYNTHEZIABLE VHDL TWO WIRE INTERFACE
4
--
5
--===========================================================================
6
--
7
-- This core adheres to the GNU public license  
8
--
9
-- Design units   : TWI Master core
10
--
11
-- File name      : twi.vhd
12
--
13
-- Purpose        : Implements an I2C master Interface 
14
--                  
15
-- Dependencies   : ieee.std_logic_1164
16
--                  ieee.numeric_std
17
--                  unisim.vcomponents
18
--
19
-- Revision list  :
20
--
21
-- Version Author        Date         Changes
22
--
23
-- 0.1     John Kent     2010-05-04   New model
24
--
25
--         dilbert57@opencores.org
26
--
27
library ieee;
28
use ieee.std_logic_1164.all;
29
use ieee.numeric_std.all;
30
library unisim;
31
      use unisim.vcomponents.all;
32
 
33
-----------------------------------------------------------------------
34
-- Entity for TWI                                                    --
35
-----------------------------------------------------------------------
36
 
37
entity twi is
38
  generic (
39
    CLK_FREQ : integer := 25_000_000;
40
  );
41
 
42
  port (
43
    --
44
    -- CPU signals
45
    --
46
    clk      : in  std_logic;                     -- System Clock
47
    rst      : in  std_logic;                     -- Reset input (active high)
48
    cs       : in  std_logic;                     -- Chip Select
49
    rw       : in  std_logic;                     -- Read / Not Write
50
    irq      : out std_logic;                     -- Interrupt
51
    addr     : in  std_logic;                     -- Register Select
52
    data_in  : in  std_logic_vector(7 downto 0);  -- Data Bus In 
53
    data_out : out std_logic_vector(7 downto 0);  -- Data Bus Out
54
 
55
    -- I2C Signals
56
    --
57
    scl     : inout std_logic;                    -- serial clock
58
    sda     : inout std_logic                     -- serial data
59
    );
60
end twi;
61
 
62
-------------------------------------------------------------------------------
63
-- Architecture for Two Wire Interface registers
64
-------------------------------------------------------------------------------
65
 
66
architecture rtl of twi is
67
 
68
  -----------------------------------------------------------------------------
69
  -- Signals
70
  -----------------------------------------------------------------------------
71
 
72
  ----------------------------------------------------------------------
73
  --  Status Register: twi_status_reg 
74
  ----------------------------------------------------------------------
75
  --
76
  -- IO address + 0 Read
77
  --
78
  --+-------+-------+-------+-------+-------+-------+-------+-------+
79
  --| RXIRQ | TXIRQ | ACKE  |       |       |       | TXRDY | RXRDY |
80
  --+-------+-------+-------+-------+-------+-------+-------+-------+
81
  -- RXIRQ - Bit[7] - Receive Interrupt Request
82
  -- TXIRQ - Bit[6] - Transmit Interrupt Request
83
  -- ACKE  - Bit[5] - Acknowledge Error
84
  -- TXRDY - Bit[1] - Transmit Ready (byte transmitted)
85
  -- RXRDY - Bit[0] - Receive Ready (byte received)
86
  -- 
87
  signal twi_status_reg : std_logic_vector(7 downto 0) := (others => '0');
88
 
89
  ----------------------------------------------------------------------
90
  --  Control Register: twi_control_reg
91
  ----------------------------------------------------------------------
92
  --
93
  -- IO address + 0 Write
94
  --
95
  --+--------+-------+--------+--------+--------+--------+--------+--------+
96
  --|  RXIE  | TXIE  | TWPS(1)| TWPS(0)| TWBR(3)| TWBR(2)| TWBR(1)| TWBR(0)|
97
  --+--------+-------+--------+--------+--------+--------+--------+--------+
98
  -- RXIE - Bit[7]
99
  -- 0       - Rx Interrupt disabled
100
  -- 1       - Rx Interrupt enabled
101
  -- TXIE - Bit[6]
102
  -- 0       - Tx Interrupt disabled
103
  -- 1       - Tx Interrupt enabled
104
  --
105
  -- SCL frequency = CPU Clock Frequency / ( 16 + 2(TWBR) . 4^TWPS)
106
  --
107
  -- TWPS - Bits[5..4]
108
  -- 0 0     - Prescale by  1
109
  -- 0 1     - Prescale by  4
110
  -- 1 0     - Prescale by 16
111
  -- 1 1     - Prescale by 64
112
  --
113
  -- TWBR - Bits[3..0]
114
  -- 0 0 0 0   - Baud Clk divide by  1
115
  -- 0 0 0 1   - Baud Clk divide by  2
116
  -- 0 0 1 0   - Baud Clk divide by  3
117
  -- 0 0 1 1   - Baud Clk divide by  4
118
  -- 0 1 0 0   - Baud Clk divide by  5
119
  -- 0 1 0 1   - Baud Clk divide by  6
120
  -- 0 1 1 0   - Baud Clk divide by  7
121
  -- 0 1 1 1   - Baud Clk divide by  8
122
  -- 1 0 0 0   - Baud Clk divide by  9
123
  -- 1 0 0 1   - Baud Clk divide by 10
124
  -- 1 0 1 0   - Baud Clk divide by 11
125
  -- 1 0 1 1   - Baud Clk divide by 12
126
  -- 1 1 0 0   - Baud Clk divide by 13
127
  -- 1 1 0 1   - Baud Clk divide by 14
128
  -- 1 1 1 0   - Baud Clk divide by 15
129
  -- 1 1 1 1   - Baud Clk divide by 16
130
 
131
 
132
  signal twi_control_reg : std_logic_vector(7 downto 0) := (others => '0'); -- control register
133
 
134
  ----------------------------------------------------------------------
135
  -- Receive Register
136
  ----------------------------------------------------------------------
137
  --
138
  -- IO address + 1     Read
139
  --
140
  signal twi_rx_reg : std_logic_vector(7 downto 0) := (others => '0');
141
 
142
  ----------------------------------------------------------------------
143
  -- Transmit Register
144
  ----------------------------------------------------------------------
145
  --
146
  -- IO address + 1     Write
147
  --
148
  signal twi_tx_reg : std_logic_vector(7 downto 0) := (others => '0');
149
 
150
  signal Reset    : std_logic;          -- Reset (Software & Hardware)
151
  signal RxRst    : std_logic;          -- Receive Reset (Software & Hardware)
152
  signal TxRst    : std_logic;          -- Transmit Reset (Software & Hardware)
153
  signal TxDbit   : std_logic;          -- Transmit data bit
154
  signal RxDR     : std_logic := '0';   -- Receive Data ready
155
  signal TxIdle   : std_logic;          -- Transmitter idle
156
  signal TxBE     : std_logic := '0';   -- Transmit buffer empty
157
  signal TxAck    : std_logic;          -- Byte transmitted to transmitter
158
  --
159
  signal FErr     : std_logic := '0';   -- Frame error
160
  signal OErr     : std_logic := '0';   -- Output error
161
  signal PErr     : std_logic := '0';   -- Parity Error
162
  --
163
  signal TxIEnb   : std_logic := '0';   -- Transmit interrupt enable
164
  signal RxIEnb   : std_logic := '0';   -- Receive interrupt enable
165
  --
166
  signal ReadRR   : std_logic := '0';   -- Read receive buffer
167
  signal WriteTR  : std_logic := '0';   -- Write transmit buffer
168
  signal ReadSR   : std_logic := '0';   -- Read Status register
169
  --
170
  signal DCDState : DCD_State_Type;     -- DCD Reset state sequencer
171
  signal DCDDel   : std_logic := '0';   -- Delayed DCD_n
172
  signal DCDEdge  : std_logic := '0';   -- Rising DCD_N Edge Pulse
173
  signal DCDInt   : std_logic := '0';   -- DCD Interrupt
174
 
175
begin
176
  -----------------------------------------------------------------------------
177
  -- Instantiation of internal components
178
  -----------------------------------------------------------------------------
179
 
180
  RxDev : entity ACIA_RX port map (
181
    Clk    => clk,
182
    RxRst  => RxRst,
183
    RxRd   => ReadRR,
184
    WdFmt  => CtrlReg(4 downto 2),
185
    BdFmt  => CtrlReg(1 downto 0),
186
    RxClk  => RxC,
187
    RxDat  => RxD,
188
    RxFErr => FErr,
189
    RxOErr => OErr,
190
    RxPErr => PErr,
191
    RxRdy  => RxDR,
192
    RxDout => RecvReg
193
   );
194
 
195
  TxDev : entity ACIA_TX port map (
196
    Clk   => clk,
197
    Reset => TxRst,
198
    Wr    => WriteTR,
199
    Din   => TxReg,
200
    WdFmt => CtrlReg(4 downto 2),
201
    BdFmt => CtrlReg(1 downto 0),
202
    TxClk => TxC,
203
    Dat   => TxDbit,
204
    Empty => TxIdle
205
   );
206
 
207
---------------------------------------------------------------
208
-- ACIA Reset may be hardware or software
209
---------------------------------------------------------------
210
  ACIA_Reset : process(clk, rst)
211
  begin
212
    -- Asynchronous External reset
213
    if rst = '1' then
214
      Reset <= '1';
215
    elsif falling_edge(clk) then
216
      -- Synchronous Software reset
217
      Reset <= CtrlReg(1) and CtrlReg(0);
218
    end if;
219
 
220
  end process;
221
 
222
  -- Transmitter reset
223
  TxRst <= Reset;
224
  -- Receiver reset
225
  RxRst <= Reset or DCD_n;
226
 
227
  -----------------------------------------------------------------------------
228
  -- ACIA Status Register
229
  -----------------------------------------------------------------------------
230
 
231
  ACIA_Status : process(Reset, clk)
232
  begin
233
    if Reset = '1' then
234
      StatReg <= (others => '0');
235
    elsif falling_edge(clk) then
236
      StatReg(0) <= RxDR;                  -- Receive Data Ready
237
      StatReg(1) <= TxBE and (not CTS_n);  -- Transmit Buffer Empty
238
      StatReg(2) <= DCDInt;                -- Data Carrier Detect
239
      StatReg(3) <= CTS_n;                 -- Clear To Send
240
      StatReg(4) <= FErr;                  -- Framing error
241
      StatReg(5) <= OErr;                  -- Overrun error
242
      StatReg(6) <= PErr;                  -- Parity error
243
      StatReg(7) <= (RxIEnb and RxDR) or
244
                    (RxIEnb and DCDInt) or
245
                    (TxIEnb and TxBE);
246
    end if;
247
  end process;
248
 
249
 
250
-----------------------------------------------------------------------------
251
-- ACIA Transmit Control
252
-----------------------------------------------------------------------------
253
 
254
  ACIA_Control : process(CtrlReg, TxDbit)
255
  begin
256
    case CtrlReg(6 downto 5) is
257
      when "00" =>                      -- Disable TX Interrupts, Assert RTS
258
        TxD    <= TxDbit;
259
        TxIEnb <= '0';
260
      when "01" =>                      -- Enable TX interrupts, Assert RTS
261
        TxD    <= TxDbit;
262
        TxIEnb <= '1';
263
      when "10" =>                      -- Disable Tx Interrupts, Clear RTS
264
        TxD    <= TxDbit;
265
        TxIEnb <= '0';
266
      when "11" =>                      -- Disable Tx interrupts, Assert RTS, send break
267
        TxD    <= '0';
268
        TxIEnb <= '0';
269
      when others =>
270
        null;
271
    end case;
272
 
273
    RxIEnb <= CtrlReg(7);
274
  end process;
275
 
276
  tx_process : process(clk, reset)
277
  begin
278
    if reset = '1' then
279
      WriteTR <= '0';
280
      TxAck   <= '0';
281
    elsif falling_edge(clk) then
282
      WriteTR <= '0';
283
      TxAck   <= '0';
284
      if TxBE = '0' and TxIdle = '1' then
285
        WriteTR <= '1';
286
        TxAck   <= '1';
287
      end if;
288
    end if;
289
  end process;
290
 
291
-----------------------------------------------------------------------------
292
-- Generate Read / Write strobes.
293
-----------------------------------------------------------------------------
294
 
295
  ACIA_Read_Write : process(clk, Reset)
296
  begin
297
    if reset = '1' then
298
      CtrlReg <= (others => '0');
299
      TxReg   <= (others => '0');
300
      ReadRR  <= '0';
301
      ReadSR  <= '0';
302
      TxBE    <= '1';
303
    elsif falling_edge(clk) then
304
      ReadRR <= '0';
305
      ReadSR <= '0';
306
      if TxAck = '1' then
307
        TxBE <= '1';
308
      end if;
309
      if cs = '1' then
310
        if Addr = '0' then              -- Control / Status register
311
          if rw = '0' then              -- write control register
312
            CtrlReg <= DataIn;
313
          else                          -- read status register
314
            ReadSR <= '1';
315
          end if;
316
        else                            -- Data Register
317
          if rw = '0' then              -- write transmiter register
318
            TxReg <= DataIn;
319
            TxBE  <= '0';
320
          else                          -- read receiver register
321
            ReadRR <= '1';
322
          end if;
323
        end if;
324
      end if;
325
    end if;
326
  end process;
327
 
328
---------------------------------------------------------------
329
-- Set Data Output Multiplexer
330
--------------------------------------------------------------
331
 
332
  ACIA_Data_Mux : process(Addr, RecvReg, StatReg)
333
  begin
334
    if Addr = '1' then
335
      DataOut <= RecvReg;               -- read receiver register
336
    else
337
      DataOut <= StatReg;               -- read status register
338
    end if;
339
  end process;
340
 
341
  irq <= StatReg(7);
342
 
343
---------------------------------------------------------------
344
-- Data Carrier Detect Edge rising edge detect
345
---------------------------------------------------------------
346
  ACIA_DCD_edge : process(reset, clk)
347
  begin
348
    if reset = '1' then
349
      DCDEdge <= '0';
350
      DCDDel  <= '0';
351
    elsif falling_edge(clk) then
352
      DCDDel  <= DCD_n;
353
      DCDEdge <= DCD_n and (not DCDDel);
354
    end if;
355
  end process;
356
 
357
 
358
---------------------------------------------------------------
359
-- Data Carrier Detect Interrupt
360
---------------------------------------------------------------
361
-- If Data Carrier is lost, an interrupt is generated
362
-- To clear the interrupt, first read the status register
363
--      then read the data receive register
364
 
365
  ACIA_DCD_Int : process(reset, clk)
366
  begin
367
    if reset = '1' then
368
      DCDInt   <= '0';
369
      DCDState <= DCD_State_Idle;
370
    elsif falling_edge(clk) then
371
      case DCDState is
372
        when DCD_State_Idle =>
373
          -- DCD Edge activates interrupt
374
          if DCDEdge = '1' then
375
            DCDInt   <= '1';
376
            DCDState <= DCD_State_Int;
377
          end if;
378
        when DCD_State_Int =>
379
          -- To reset DCD interrupt, 
380
          -- First read status
381
          if ReadSR = '1' then
382
            DCDState <= DCD_State_Reset;
383
          end if;
384
        when DCD_State_Reset =>
385
          -- Then read receive register
386
          if ReadRR = '1' then
387
            DCDInt   <= '0';
388
            DCDState <= DCD_State_Idle;
389
          end if;
390
        when others =>
391
          null;
392
      end case;
393
    end if;
394
  end process;
395
 
396
  rts_n <= RxDR;
397
 
398
end rtl;
399
 

powered by: WebSVN 2.1.0

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