~ruther/vhdl-i2c

ref: 15eb81c6daee1b663491ca1f7f4ecc1d464f2b0c vhdl-i2c/src/mcu_slave/regs.vhd -rw-r--r-- 3.7 KiB
15eb81c6 — Rutherther feat: add counter and register testing slave top levels 1 year, 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library utils;
library i2c;

entity regs is

  generic (
    MAX : integer := 100);

  port (
    clk_i  : in std_logic;
    rst_i : in std_logic;
    err_noack_o : out std_logic;
    bus_busy_o : out std_logic;
    dev_busy_o : out std_logic;
    sda_io : inout std_logic;
    scl_io : inout std_logic);

end entity regs;

architecture a1 of regs is
  constant ADDRESS : std_logic_vector(6 downto 0) := "1110101";

  constant REGS_COUNT : integer := 20;
  type regs_t is array (0 to REGS_COUNT - 1) of std_logic_vector(7 downto 0);
  signal curr_regs : regs_t;
  signal next_regs : regs_t;

  signal rst_n : std_logic;

  signal sda, scl : std_logic;
  signal sda_enable, scl_enable : std_logic;

  signal tx_valid, tx_ready, tx_clear_buffer : std_logic;
  signal tx_data : std_logic_vector(7 downto 0);

  signal rx_valid, rx_confirm : std_logic;
  signal rx_data : std_logic_vector(7 downto 0);

  signal curr_reg_address_filled : std_logic;
  signal next_reg_address_filled : std_logic;

  signal curr_reg_address : unsigned(7 downto 0);
  signal next_reg_address : unsigned(7 downto 0);

  signal dev_busy : std_logic;

  signal curr_dev_busy : std_logic;
  signal next_dev_busy : std_logic;

  signal rw : std_logic;
begin
  rst_n <= not rst_i;
  dev_busy_o <= dev_busy;

  next_dev_busy <= dev_busy;

  next_reg_address_filled <= '0' when curr_dev_busy = '0' and dev_busy = '1' and rw = '0' else
                             '1' when curr_reg_address_filled = '0' and rx_valid = '1' else
                             curr_reg_address_filled;

  rx_confirm <= rx_valid;

  next_reg_address <= unsigned(rx_data) when rx_valid = '1' and curr_reg_address_filled = '0' else
                      (curr_reg_address + 1) mod REGS_COUNT when rx_valid = '1' else
                      (curr_reg_address + 1) mod REGS_COUNT when tx_valid = '1' and dev_busy = '1' and rw = '1' else
                      curr_reg_address;

  tx_clear_buffer <= not curr_reg_address_filled;
  tx_data <= curr_regs(to_integer(curr_reg_address));
  tx_valid <= '1' when tx_ready = '1' and dev_busy = '1' and rw = '1' else
              '0';

  set_next_regs: process (all) is
  begin  -- process set_next_regs
    next_regs <= curr_regs;

    if rx_valid = '1' and curr_reg_address_filled = '1' then
      next_regs(to_integer(curr_reg_address)) <= rx_data;
    end if;
  end process set_next_regs;

  uut: entity i2c.slave
    generic map (
      SCL_FALLING_DELAY => 1)
    port map (
      clk_i          => clk_i,
      rst_in         => rst_n,
      address_i      => ADDRESS,
      generate_ack_i => '1',
      expect_ack_i   => '1',

      rx_valid_o     => rx_valid,
      rx_data_o      => rx_data,
      rx_confirm_i   => rx_confirm,
      rx_stretch_i   => '0',

      tx_ready_o     => tx_ready,
      tx_valid_i     => tx_valid,
      tx_data_i      => tx_data,
      tx_stretch_i   => '0',
      tx_clear_buffer_i => tx_clear_buffer,

      err_noack_o    => err_noack_o,
      rw_o           => rw,
      dev_busy_o     => dev_busy,
      bus_busy_o     => bus_busy_o,
      sda_i          => sda,
      scl_i          => scl,
      sda_enable_o   => sda_enable,
      scl_enable_o   => scl_enable);

  sda_open_buffer: entity utils.open_drain_buffer
    port map (
      pad_io   => sda_io,
      enable_i => sda_enable,
      state_o  => sda);
  scl_open_buffer: entity utils.open_drain_buffer
    port map (
      pad_io   => scl_io,
      enable_i => scl_enable,
      state_o  => scl);

  set_regs: process (clk_i) is
  begin  -- process set_regs
    if rising_edge(clk_i) then          -- rising clock edge
      if rst_n = '0' then              -- synchronous reset (active low)
      else
      end if;
    end if;
  end process set_regs;

end architecture a1;
Do not follow this link