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

Subversion Repositories iicmb

[/] [iicmb/] [trunk/] [src/] [mbyte.vhd] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sshuv2
 
2
--==============================================================================
3
--                                                                             |
4
--    Project: IIC Multiple Bus Controller (IICMB)                             |
5
--                                                                             |
6
--    Module:  Byte layer FSM (master mode).                                   |
7
--    Version:                                                                 |
8
--             1.0,   April 29, 2016                                           |
9
--                                                                             |
10
--    Author:  Sergey Shuvalkin, (sshuv2@opencores.org)                        |
11
--                                                                             |
12
--==============================================================================
13
--==============================================================================
14
-- Copyright (c) 2016, Sergey Shuvalkin                                        |
15
-- All rights reserved.                                                        |
16
--                                                                             |
17
-- Redistribution and use in source and binary forms, with or without          |
18
-- modification, are permitted provided that the following conditions are met: |
19
--                                                                             |
20
-- 1. Redistributions of source code must retain the above copyright notice,   |
21
--    this list of conditions and the following disclaimer.                    |
22
-- 2. Redistributions in binary form must reproduce the above copyright        |
23
--    notice, this list of conditions and the following disclaimer in the      |
24
--    documentation and/or other materials provided with the distribution.     |
25
--                                                                             |
26
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
27
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   |
28
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  |
29
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE    |
30
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR         |
31
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF        |
32
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS    |
33
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN     |
34
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)     |
35
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  |
36
-- POSSIBILITY OF SUCH DAMAGE.                                                 |
37
--==============================================================================
38
 
39
 
40
library ieee;
41
use ieee.std_logic_1164.all;
42
use ieee.numeric_std.all;
43
 
44
use work.iicmb_pkg.all;
45
use work.iicmb_int_pkg.all;
46
 
47
 
48
--==============================================================================
49
entity mbyte is
50
  generic
51
  (
52
    ------------------------------------
53
    g_bus_num   :       positive range 1 to 16 := 1;               -- Number of separate I2C buses
54
    g_f_clk     :       real                   := 100000.0         -- Frequency of system clock 'clk' (in kHz)
55
    ------------------------------------
56
  );
57
  port
58
  (
59
    ------------------------------------
60
    clk         : in    std_logic;                                 -- Clock
61
    s_rst       : in    std_logic;                                 -- Synchronous reset (active high)
62
    ------------------------------------
63
    ------------------------------------
64
    captured    :   out std_logic := '0';                          -- 'Bus is captured' indication (captured = high)
65
    busy        : in    std_logic;                                 -- 'Bus is busy' indication (busy = high)
66
    bus_id      :   out natural range 0 to g_bus_num - 1 := 0;     -- Bus selector
67
    fsm_state   :   out std_logic_vector(3 downto 0);              -- FSM state
68
    ------------------------------------
69
    ------------------------------------
70
    mcmd_wr     : in    std_logic;                                 -- Byte command write (active high)
71
    mcmd_id     : in    std_logic_vector(2 downto 0);              -- Byte command ID
72
    mcmd_data   : in    std_logic_vector(7 downto 0);              -- Byte command data
73
    ------------------------------------
74
    ------------------------------------
75
    mrsp_wr     :   out std_logic                    := '0';       -- Byte command response write (active high)
76
    mrsp_id     :   out std_logic_vector(2 downto 0) := mrsp_done; -- Byte command response control bit
77
    mrsp_data   :   out std_logic_vector(7 downto 0);              -- Byte command response data
78
    ------------------------------------
79
    ------------------------------------
80
    mbc_wr      :   out std_logic                    := '0';       -- Bit command write (active high)
81
    mbc         :   out mbc_type                     := mbc_stop;  -- Bit command
82
    ------------------------------------
83
    ------------------------------------
84
    mbr_wr      : in    std_logic;                                 -- Bit command response write (active high)
85
    mbr         : in    mbr_type                                   -- Bit command response
86
    ------------------------------------
87
  );
88
end entity mbyte;
89
--==============================================================================
90
 
91
--==============================================================================
92
architecture rtl of mbyte is
93
 
94
  constant c_cycle_cnt_inc : integer := 1;
95
  constant c_cycle_cnt_max : integer := integer(g_f_clk);
96
  constant c_cycle_cnt_thr : integer := c_cycle_cnt_max - c_cycle_cnt_inc;
97
 
98
  type state_type is
99
  (
100
    s_idle,          -- Idle
101
    s_bus_taken,     -- Bus is taken
102
    s_start_pending, -- Waiting for right moment to capture bus
103
    s_start,         -- Sending Start Condition (Capturing the bus)
104
    s_stop,          -- Sending Stop Condition (Releasing the bus)
105
    s_write,         -- Sending a byte
106
    s_read,          -- Receiving a byte
107
    s_wait           -- Receiving a byte
108
  );
109
 
110
  ------------------------------------------------------------------------------
111
  -- Converting states to std_logic_vector
112
  function to_std_logic_vector(a : state_type) return std_logic_vector is
113
  begin
114
    case (a) is
115
      when s_idle          => return "0000";
116
      when s_bus_taken     => return "0001";
117
      when s_start_pending => return "0010";
118
      when s_start         => return "0011";
119
      when s_stop          => return "0100";
120
      when s_write         => return "0101";
121
      when s_read          => return "0110";
122
      when s_wait          => return "0111";
123
    end case;
124
  end function to_std_logic_vector;
125
  ------------------------------------------------------------------------------
126
 
127
  signal   state           : state_type                         := s_idle;
128
  signal   cnt             : integer range 0 to 8               := 0;
129
  signal   sbuf            : std_logic_vector(7 downto 0)       := (others => '0');
130
  signal   ack             : std_logic                          := '0';
131
  signal   cycle_cnt       : integer range 0 to c_cycle_cnt_max := 0;
132 8 sshuv2
  signal   ms_cnt          : unsigned( 7 downto 0)              := to_unsigned(0, 8);
133 2 sshuv2
 
134
begin
135
 
136
  mrsp_data <= sbuf;
137
  fsm_state <= to_std_logic_vector(state);
138
 
139
  ------------------------------------------------------------------------------
140
  -- Main FSM:
141
  main_fsm_proc:
142
  process(clk)
143
    ---------
144
    procedure bit_command(a : mbc_type) is
145
    begin
146
      mbc_wr <= '1';
147
      mbc    <= a;
148
    end procedure bit_command;
149
    ---------
150
    ---------
151
    procedure bit_command(a : std_logic) is
152
    begin
153
      mbc_wr <= '1';
154
      if (a = '0') then
155
        mbc <= mbc_write_0;
156
      else
157
        mbc <= mbc_write_1;
158
      end if;
159
    end procedure bit_command;
160
    ---------
161
    ---------
162
    function get_bit(a : mbr_type) return std_logic is
163
    begin
164
      if (a = mbr_bit_0) then
165
        return '0';
166
      else
167
        return '1';
168
      end if;
169
    end function get_bit;
170
    ---------
171
    ---------
172
    procedure byte_response(a : std_logic_vector(2 downto 0)) is
173
    begin
174
      mrsp_wr <= '1';
175
      mrsp_id <= a;
176
    end procedure byte_response;
177
    ---------
178
    variable v_bus_id   : integer range 0 to 15;
179
  begin
180
    if rising_edge(clk) then
181
      if (s_rst = '1') then
182
        state     <= s_idle;
183
        cnt       <= 0;
184
        sbuf      <= (others => '0');
185
        ack       <= '0';
186
        mbc_wr    <= '0';
187
        mbc       <= mbc_stop;
188
        mrsp_wr   <= '0';
189
        mrsp_id   <= mrsp_done;
190
        bus_id    <= 0;
191
        captured  <= '0';
192
        cycle_cnt <= 0;
193 8 sshuv2
        ms_cnt    <= to_unsigned(0, 8);
194 2 sshuv2
      else
195
        -- Default:
196
        mbc_wr    <= '0';
197
        mrsp_wr   <= '0';
198
        ------
199
 
200
        case (state) is
201
          -- 'Idle' state ----------------------------------
202
          when s_idle =>
203
            if (mcmd_wr = '1') then
204
              case (mcmd_id) is
205
                when mcmd_start =>
206
                  -- Begin procedure of bus capturing
207
                  state     <= s_start_pending;
208
                when mcmd_set_bus =>
209
                  -- Switch to another bus
210
                  state     <= s_idle;
211
                  v_bus_id  := to_integer(unsigned(mcmd_data(3 downto 0)));
212
                  if (v_bus_id > (g_bus_num - 1)) then
213
                    byte_response(mrsp_error);
214
                  else
215
                    bus_id    <= v_bus_id;
216
                    byte_response(mrsp_done);
217
                  end if;
218
                when mcmd_wait =>
219
                  -- Wait for specified period:
220
                  state     <= s_wait;
221
                  cycle_cnt <= 0;
222 8 sshuv2
                  ms_cnt    <= unsigned(mcmd_data);
223 2 sshuv2
                when others =>
224
                  -- Other commands are rejected in 'Idle' state
225
                  state     <= s_idle;
226
                  byte_response(mrsp_error);
227
              end case;
228
              cnt       <= 0;
229
            end if;
230
            captured  <= '0';
231
          -- 'Idle' state ----------------------------------
232
 
233
          -- 'Wait' state ----------------------------------
234
          when s_wait =>
235
            captured  <= '0';
236 8 sshuv2
            if (ms_cnt = 0) then
237 2 sshuv2
              state     <= s_idle;
238
              byte_response(mrsp_done);
239
            else
240
              if (cycle_cnt < c_cycle_cnt_thr) then
241
                cycle_cnt <= cycle_cnt + c_cycle_cnt_inc;
242
              else
243
                cycle_cnt <= cycle_cnt - c_cycle_cnt_thr;
244 8 sshuv2
                ms_cnt    <= ms_cnt - 1;
245 2 sshuv2
              end if;
246
            end if;
247
          -- 'Wait' state ----------------------------------
248
 
249
          -- 'Bus is Taken' state --------------------------
250
          when s_bus_taken =>
251
            if (mcmd_wr = '1') then
252
              case (mcmd_id) is
253
                when mcmd_start =>
254
                  -- Generate Repeated Start condition
255
                  state     <= s_start;
256
                  bit_command(mbc_start);
257
                when mcmd_read_ack =>
258
                  -- Byte reading with acknowledge
259
                  state     <= s_read;
260
                  ack       <= '0';
261
                  bit_command(mbc_read);
262
                when mcmd_read_nak =>
263
                  -- Byte reading with not-acknowledge
264
                  state     <= s_read;
265
                  ack       <= '1';
266
                  bit_command(mbc_read);
267
                when mcmd_stop =>
268
                  -- Issue Stop condition
269
                  state     <= s_stop;
270
                  bit_command(mbc_stop);
271
                when mcmd_write =>
272
                  -- Byte writing
273
                  state     <= s_write;
274
                  sbuf      <= mcmd_data(6 downto 0) & '0';
275
                  bit_command(mcmd_data(7));
276
                when others =>
277
                  -- Other commands are rejected in 'Bus Is Taken' state
278
                  state     <= s_bus_taken;
279
                  byte_response(mrsp_error);
280
              end case;
281
              cnt       <= 0;
282
            end if;
283
            captured <= '1';
284
          -- 'Bus is Taken' state --------------------------
285
 
286
          -- 'Start is Pending' state ----------------------
287
          when s_start_pending =>
288
            captured  <= '0';
289
            if (busy = '0') then
290
              state     <= s_start;
291
              bit_command(mbc_start);
292
            end if;
293
          -- 'Start is Pending' state ----------------------
294
 
295
          -- 'Start' state ---------------------------------
296
          when s_start =>
297
            if (mbr_wr = '1') then
298
              if (mbr = mbr_done) then
299
                state     <= s_bus_taken;
300
                captured  <= '1';
301
                byte_response(mrsp_done);
302
              else
303
                -- (mbr = mbr_arb_lost)
304
                state     <= s_idle;
305
                captured  <= '0';
306
                byte_response(mrsp_arb_lost);
307
              end if;
308
            end if;
309
          -- 'Start' state ---------------------------------
310
 
311
          -- 'Stop' state ----------------------------------
312
          when s_stop =>
313
            captured  <= '1';
314
            if (mbr_wr = '1') then
315
              state     <= s_idle;
316
              captured  <= '0';
317
              byte_response(mrsp_done);
318
            end if;
319
          -- 'Stop' state ----------------------------------
320
 
321
          -- 'Byte Reading' state --------------------------
322
          when s_read =>
323
            captured  <= '1';
324
            if (mbr_wr = '1') then
325
              case (cnt) is
326
                when 8 =>
327
                  if (mbr = mbr_done) then
328
                    -- Return to 'Bus Is Taken' state and
329
                    -- respond with a byte of data.
330
                    state     <= s_bus_taken;
331
                    byte_response(mrsp_byte);
332
                  else
333
                    -- (mbr = mbr_arb_lost)
334
                    state     <= s_idle;
335
                    captured  <= '0';
336
                    byte_response(mrsp_arb_lost);
337
                  end if;
338
                when others =>
339
                  if (mbr = mbr_error) then
340
                    state     <= s_idle;
341
                    captured  <= '0';
342
                    byte_response(mrsp_error);
343
                  else
344
                    -- (mbr = mbr_bit_0)or(mbr = mbr_bit_1)
345
                    sbuf      <= sbuf(6 downto 0) & get_bit(mbr);
346
                    cnt       <= cnt + 1;
347
                    if (cnt = 7) then
348
                      -- Write Ack/Nak
349
                      bit_command(ack);
350
                    else
351
                      -- Read a bit
352
                      bit_command(mbc_read);
353
                    end if;
354
                  end if;
355
              end case;
356
            end if;
357
          -- 'Byte Reading' state --------------------------
358
 
359
          -- 'Byte Writing' state --------------------------
360
          when s_write =>
361
            captured  <= '1';
362
            if (mbr_wr = '1') then
363
              case (cnt) is
364
                when 8 =>
365
                  state     <= s_bus_taken;
366
                  if (mbr = mbr_error) then
367
                    -- Something went wrong
368
                    state     <= s_idle;
369
                    captured  <= '0';
370
                    byte_response(mrsp_error);
371
                  elsif (mbr = mbr_bit_0) then
372
                    -- Write is acknowledged
373
                    byte_response(mrsp_done);
374
                  else
375
                    -- Write is not acknowledged
376
                    byte_response(mrsp_nak);
377
                  end if;
378
                when others =>
379
                  if (mbr = mbr_done) then
380
                    sbuf      <= sbuf(6 downto 0) & '0';
381
                    cnt       <= cnt + 1;
382
                    if (cnt = 7) then
383
                      -- Read Ack/Nak
384
                      bit_command(mbc_read);
385
                    else
386
                      -- Write a bit
387
                      bit_command(sbuf(7));
388
                    end if;
389
                  else
390
                    -- (mbr = mbr_arb_lost)
391
                    state     <= s_idle;
392
                    captured  <= '0';
393
                    byte_response(mrsp_arb_lost);
394
                  end if;
395
              end case;
396
            end if;
397
          -- 'Byte Writing' state --------------------------
398
        end case;
399
      end if;
400
    end if;
401
  end process main_fsm_proc;
402
  ------------------------------------------------------------------------------
403
 
404
end architecture rtl;
405
--==============================================================================
406
 

powered by: WebSVN 2.1.0

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