x393  1.0
FPGAcodeforElphelNC393camera
sensor_i2c_scl_sda.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
42  input mrst, // @ posedge mclk
43  input mclk, // global clock
44  input i2c_rst,
45  input [ 7:0] i2c_dly, // bit duration-1 (>=2?), 1 unit - 4 mclk periods
46  input active_sda, // active pull SDA
47  input early_release_0,// release SDA immediately after end of SCL if next bit is 1 (for ACKN). Data hold time by slow 0->1
48  input snd_start,
49  input snd_stop,
50  input snd9,
51  input rcv, // receive mode (valid with snd9) - master receives, slave - sends
52  input [ 8:0] din,
53  output reg [ 8:0] dout, //
54  output reg dout_stb, // dout contains valid data
55  output reg scl, // i2c SCL signal
56  input sda_in, // i2c SDA signal form I/O pad
57  output reg sda, // i2c SDA signal
58  output reg sda_en, // drive SDA when SDA=0 and during second half of SCL = 0 interval (also during stop)
59  output ready, // ready to accept commands
60  output reg bus_busy, // i2c bus busy (1 cycle behind !ready)
61  output is_open // i2c channel is open (started, no stop yet)
62 );
63  wire rst = mrst || i2c_rst;
64  reg is_open_r;
65  reg [8:0] sr;
66  reg [7:0] dly_cntr;
67  reg busy_r;
68  wire snd_start_w = snd_start && ready; //!busy_r;
69  wire snd_stop_w = snd_stop && ready; // !busy_r;
70  wire snd9_w = snd9 && ready; //!busy_r;
71  wire start_w = (snd_start || snd_stop || snd9_w) && ready; //!busy_r;
73  reg dly_over;
74 // reg dly_over_d;
75  reg [3:0] seq_start_restart;
76  reg [2:0] seq_stop;
77  reg [3:0] seq_bit;
78  reg [3:0] bits_left;
79  reg done_r;
80  reg sda_r;
81  reg first_cyc; // first clock cycle for the delay interval - update SCL/SDA outputs
82  reg active_sda_r; // registered @ snd9, disable in rcv mode
83  reg active_sda_was_0; // only use active SDA if previous bit was 0 or it is receive mode
84  reg early_release_r; // to enable it only for LSB before ACKN during send
85  reg rcv_r;
86  wire busy_w = busy_r && ! done_r;
87 // wire pre_dout_stb = dly_over && seq_bit[0] && (bits_left == 0);
88 // assign ready = !busy_r;
89  assign ready = !busy_w;
90 
91  assign is_open = is_open_r;
92 // assign dout = sr;
93  always @ (posedge mclk) begin
94  active_sda_was_0 <= !sda || rcv_r;
95  if (snd9_w) rcv_r <= rcv;
96 
97  early_release_r <= early_release_0 && !rcv_r && (bits_left == 1); // only before ACN during master send
98 
99  // disable active_sda in send messages for the last (ACKN) bit, for the receive - all but ACKN
100  if (snd9_w) active_sda_r <= active_sda && !rcv;
102  else if (dly_over && seq_bit[0]) active_sda_r <= active_sda && ((bits_left != 1) ^ rcv_r);
103 //active_sda_r && !sda
104  if (rst) seq_start_restart <= 0;
105  else if (snd_start_w) seq_start_restart <= (is_open_r && !seq_stop[0]) ? 4'h8 : 4'h4;
106  else if (dly_over) seq_start_restart <= {1'b0,seq_start_restart[3:1]};
107 
108  if (rst) seq_stop <= 0;
109  else if (snd_stop_w) seq_stop <= 3'h4;
110  else if (dly_over) seq_stop <= {1'b0,seq_stop[2:1]};
111 
112  if (rst) seq_bit <= 0;
113  else if (snd9_w || (seq_bit[0] && (bits_left != 0) && dly_over)) seq_bit <= 4'h8;
114  else if (dly_over) seq_bit <= {1'b0,seq_bit[3:1]};
115 
116  if (rst) bits_left <= 4'h0;
117  else if (snd9_w) bits_left <= 4'h8;
118  else if (dly_over && seq_bit[0] && (|bits_left)) bits_left <= bits_left - 1;
119 
120 
121  if (rst) busy_r <= 0;
122  else if (start_w) busy_r <= 1;
123  else if (done_r) busy_r <= 0;
124 
125 // pre_dly_over <= (dly_cntr == 3);
126  pre_dly_over <= (dly_cntr == 2);
127 
129 // dly_over_d <= dly_over;
130  if (rst) done_r <= 0;
131  else done_r <= pre_dly_over &&
132  (bits_left == 0) &&
133  (seq_start_restart[3:1] == 0) &&
134  (seq_stop[2:1] == 0) &&
135  (seq_bit[3:1] == 0);
136 
137 // if (!busy_r || dly_over_d) dly_cntr <= i2c_dly;
138 // else dly_cntr <= dly_cntr - 1;
139 
140  if (!busy_w || dly_over) dly_cntr <= i2c_dly;
141  else dly_cntr <= dly_cntr - 1;
142 
143  if (dly_over && seq_bit[1]) sda_r <= sda_in; // just before the end of SCL pulse - delay it by a few clocks to match external latencies?
144 
145  if (snd9_w) sr <= din;
146  else if (dly_over && seq_bit[0]) sr <= {sr[7:0], sda_r};
147 
148  dout_stb <= dly_over && seq_bit[0] && (bits_left == 0) && rcv_r;
149 // dout_stb <= pre_dout_stb;
150 // if (pre_dout_stb) dout <= {sr[7:0],sda_r};
151  if (done_r) dout <= {sr[7:0],sda_r};
152 
153  if (rst) is_open_r <= 0;
154  else if (dly_over && seq_start_restart[0]) is_open_r <= 1;
155  else if (dly_over && seq_stop[0]) is_open_r <= 0;
156 
157  first_cyc <= start_w || dly_over;
158 
159  if (rst) scl <= 1;
160 // else if (first_cyc) scl <= !busy_r || // Wrong whe "open"?
161  else if (first_cyc) scl <= (scl && !busy_w) || // Wrong whe "open"?
163  seq_stop[1] || seq_stop[0] ||
164  seq_bit[2] || seq_bit[1];
165 
166  if (rst) sda <= 1;
167 // else if (first_cyc) sda <= !busy_r ||
168  else if (first_cyc) sda <= (sda && !busy_w) ||
170  seq_stop[0] ||
171  (sr[8] && (|seq_bit));
172 
173  if (rst) sda_en <= 1;
174 // else if (first_cyc) sda_en <= busy_r && (
175 // TODO: no active SDA if previous SDA was 1
176  else if (first_cyc) sda_en <= busy_w && (
177  (active_sda_r && active_sda_was_0 && (seq_start_restart[3] || seq_stop[0] || (sr[8] && seq_bit[3]))) || // !sda uses output reg
178  (|seq_start_restart[1:0]) ||
179  (|seq_stop[2:1]) ||
180  (!sr[8] && (|seq_bit[3:1])) ||
181 // (!sr[8] && seq_bit[0] && (!early_release_0 || !sr[7])));
182  (!sr[8] && seq_bit[0] && (!early_release_r || !sr[7])));
183  bus_busy <= busy_r;
184  end
185 
186 endmodule
187