OpenCores
URL https://opencores.org/ocsvn/scab-master/scab-master/trunk

Subversion Repositories scab-master

[/] [scab-master/] [trunk/] [hw/] [sources/] [SCCBMaster.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ldalmasso
------------------------------------------------------------------------
2
-- Engineer:    Dalmasso Loic
3
-- Create Date: 07/10/2024
4
-- Module Name: SCCBMaster
5
-- Description:
6
--      Serial Camera Control Bus (SCCB) Master Controller for OV7670 Camera Module.
7
--              Supports:
8
--                      - Write Mode: 3-Phase Write Transmission
9
--                      - Read Mode: 2-Phase Write Transmission, then 2-Phase Read Transmission
10
--
11
-- WARNING: /!\ Require Pull-Up on SCL and SDA pins /!\
12
--
13
-- Usage:
14
--              1. Set the inputs (keep unchanged until Ready signal is de-asserted)
15
--                      * Mode (Read/Write)
16
--                      * SCCB Slave Addresss
17
--                      * Register Address
18
--                      * Register Value (Write Mode only)
19
--              2. Asserts Start input (available only when the SCCB Master is Ready)
20
--              3. SCCB Master de-asserts the Ready signal
21
--              4. SCCB Master re-asserts the Ready signal at the end of transmission (master is ready for a new transmission)
22
--              5. In Read mode only, the read value is available when its validity signal is asserted
23
--
24
-- Generics
25
--              Input   -       input_clock: Module Input Clock Frequency
26
--              Output  -       sccb_clock: SCCB Serial Clock Frequency
27
-- Ports
28
--              Input   -       i_clock: Module Input Clock
29
--              Input   -       i_mode: Read or Write Mode ('0': Write, '1': Read)
30
--              Input   -       i_slave_addr: Address of the SCCB Slave (7 bits)
31
--              Input   -       i_reg_addr: Address of the Register to Read/Write
32
--              Input   -       i_reg_value: Value of the Register to Write
33
--              Input   -       i_start: Start SCCB Transmission ('0': No Start, '1': Start)
34
--              Output  -       o_ready: Ready State of SCCB Master ('0': Not Ready, '1': Ready)
35
--              Output  -       o_read_value_valid: Validity of value of the SCCB Slave Register ('0': Not Valid, '1': Valid)
36
--              Output  -       o_read_value: Value of the SCCB Slave Register
37 3 ldalmasso
--              Output  -       o_scl: SCCB Serial Clock ('0'-'Z'(as '1') values, working with Pull-Up)
38
--              In/Out  -       io_sda: SCCB Serial Data ('0'-'Z'(as '1') values, working with Pull-Up)
39 2 ldalmasso
------------------------------------------------------------------------
40
 
41
LIBRARY IEEE;
42
USE IEEE.STD_LOGIC_1164.ALL;
43
USE IEEE.NUMERIC_STD.ALL;
44
 
45
ENTITY SCCBMaster is
46
 
47
GENERIC(
48
        input_clock: INTEGER := 12_000_000;
49
        sccb_clock: INTEGER := 100_000
50
);
51
 
52
PORT(
53
        i_clock: IN STD_LOGIC;
54
        i_mode: IN STD_LOGIC;
55
        i_slave_addr: IN STD_LOGIC_VECTOR(6 downto 0);
56
        i_reg_addr: IN STD_LOGIC_VECTOR(7 downto 0);
57
        i_reg_value: IN STD_LOGIC_VECTOR(7 downto 0);
58
        i_start: IN STD_LOGIC;
59
        o_ready: OUT STD_LOGIC;
60
        o_read_value_valid: OUT STD_LOGIC;
61
        o_read_value: OUT STD_LOGIC_VECTOR(7 downto 0);
62
        o_scl: OUT STD_LOGIC;
63
        io_sda: INOUT STD_LOGIC
64
);
65
 
66
END SCCBMaster;
67
 
68
ARCHITECTURE Behavioral of SCCBMaster is
69
 
70
------------------------------------------------------------------------
71
-- Constant Declarations
72
------------------------------------------------------------------------
73
-- SCCB Clock Dividers
74
constant CLOCK_DIV: INTEGER := input_clock / sccb_clock;
75
constant CLOCK_DIV_X2: INTEGER := CLOCK_DIV /2;
76
 
77
-- SCCB Modes ('0': Write, '1': Read)
78
constant SCCB_WRITE_MODE: STD_LOGIC := '0';
79
constant SCCB_READ_MODE: STD_LOGIC := '1';
80
 
81
-- SCCB Transmission Start Bit
82
constant TRANSMISSION_START_BIT: STD_LOGIC := '0';
83
 
84
-- SCCB Transmission Don'T Care Bit ('Z' with Pull-Up)
85
constant TRANSMISSION_DONT_CARE_BIT: STD_LOGIC := '1';
86
 
87
------------------------------------------------------------------------
88
-- Signal Declarations
89
------------------------------------------------------------------------
90
-- SCCB Master States
91
TYPE sccbState is (IDLE, START_TX, WRITE_SLAVE_ADDR, REGISTER_WRITE, REGISTER_READ, WRITE_REG_VALUE, PREP_READ_PHASE, END_TX);
92
signal state: sccbState := IDLE;
93
signal next_state: sccbState;
94
 
95
-- SCCB Input Registers
96
signal mode: STD_LOGIC_VECTOR(1 downto 0) := "00";
97
signal slave_addr: STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
98
signal reg_addr: STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
99
signal reg_value: STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
100
signal start: STD_LOGIC := '0';
101
 
102
-- SCCB Transmission Bit Counter (8 cycles per phase)
103
signal bit_counter: UNSIGNED(3 downto 0) := (others => '0');
104
 
105
-- SCCB Clock Divider
106
signal clock_divider: INTEGER range 0 to CLOCK_DIV-1 := 0;
107
signal clock_enable: STD_LOGIC := '0';
108
signal clock_enable_x2: STD_LOGIC := '0';
109
 
110
-- SCCB SCL Register
111
signal scl_reg: STD_LOGIC := '0';
112
signal scl_enable: STD_LOGIC := '0';
113
 
114
-- SCCB SDA Output
115
signal sda_out: STD_LOGIC := TRANSMISSION_DONT_CARE_BIT;
116
 
117
-- SCCB SDA Input (Valid & Value)
118
signal sda_in_valid: STD_LOGIC := '0';
119
signal sda_in_enable: STD_LOGIC := '0';
120
signal sda_in_reg: STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
121
 
122
------------------------------------------------------------------------
123
-- Module Implementation
124
------------------------------------------------------------------------
125
begin
126
 
127
        ------------------------
128
        -- SCCB Clock Divider --
129
        ------------------------
130
        process(i_clock)
131
        begin
132
                if rising_edge(i_clock) then
133
 
134
                        -- Reset Clock Divider
135
                        if (clock_divider = CLOCK_DIV-1) then
136
                                clock_divider <= 0;
137
 
138
                        -- Increment Clock Divider
139
                        else
140
                                clock_divider <= clock_divider +1;
141
                        end if;
142
                end if;
143
        end process;
144
 
145
        ------------------------
146
        -- SCCB Clock Enables --
147
        ------------------------
148
        process(i_clock)
149
        begin
150
                if rising_edge(i_clock) then
151
 
152
                        -- Clock Enable
153
                        if (clock_divider = CLOCK_DIV-1) then
154
                                clock_enable <= '1';
155
                                clock_enable_x2 <= '1';
156
                        else
157
                                clock_enable <= '0';
158
                                clock_enable_x2 <= '0';
159
                        end if;
160
 
161
                        -- Clock Enable x2
162
                        if (clock_divider = CLOCK_DIV_X2-1) then
163
                                clock_enable_x2 <= '1';
164
                        end if;
165
 
166
                end if;
167
        end process;
168
 
169
        ------------------------
170
        -- SCCB Start Handler --
171
        ------------------------
172
        process(i_clock)
173
        begin
174
                if rising_edge(i_clock) then
175
 
176
                        -- Handle Pulse (clear value when clock_enable at '1')
177
                        if (state = IDLE) then
178
                                start <= (i_start or start) and not (clock_enable);
179
                        end if;
180
                end if;
181
        end process;
182
 
183
        ------------------------
184
        -- SCCB State Machine --
185
        ------------------------
186
        process(i_clock)
187
        begin
188
                if rising_edge(i_clock) then
189
 
190
                        -- Next State (when Clock Enable)
191
                        if (clock_enable = '1') then
192
                                state <= next_state;
193
                        end if;
194
                end if;
195
        end process;
196
 
197
        -- SCCB Next State
198
        process(state, start, bit_counter, mode)
199
        begin
200
 
201
                case state is
202
                        when IDLE =>    if (start = '1') then
203
                                                                next_state <= START_TX;
204
                                                        else
205
                                                                next_state <= IDLE;
206
                                                        end if;
207
 
208
                        -- Start of Transmission
209
                        when START_TX => next_state <= WRITE_SLAVE_ADDR;
210
 
211
                        -- Write Slave Address
212
                        when WRITE_SLAVE_ADDR =>
213
                                                        if (bit_counter(3) = '1') then
214
 
215
                                                                -- Read Mode (Current Phase)
216
                                                                if (mode(0) = SCCB_READ_MODE) then
217
                                                                        next_state <= REGISTER_READ;
218
 
219
                                                                -- Write Mode
220
                                                                else
221
                                                                        next_state <= REGISTER_WRITE;
222
                                                                end if;
223
                                                        else
224
                                                                next_state <= WRITE_SLAVE_ADDR;
225
                                                        end if;
226
 
227 5 ldalmasso
                        -- Write Register Address
228 2 ldalmasso
                        when REGISTER_WRITE =>
229
                                                        if (bit_counter(3) = '1') then
230
 
231
                                                                -- Read Mode (for Next Phase)
232
                                                                if (mode(1) = SCCB_READ_MODE) then
233
                                                                        next_state <= END_TX;
234
 
235
                                                                -- Write Mode
236
                                                                else
237
                                                                        next_state <= WRITE_REG_VALUE;
238
                                                                end if;
239
                                                        else
240
                                                                next_state <= REGISTER_WRITE;
241
                                                        end if;
242
 
243
                        -- Write Register Value
244
                        when WRITE_REG_VALUE =>
245
                                                        if (bit_counter(3) = '1') then
246
                                                                next_state <= END_TX;
247
                                                        else
248
                                                                next_state <= WRITE_REG_VALUE;
249
                                                        end if;
250
 
251
                        -- Read Register Value
252
                        when REGISTER_READ =>
253
                                                        if (bit_counter(3) = '1') then
254
                                                                next_state <= END_TX;
255
                                                        else
256
                                                                next_state <= REGISTER_READ;
257
                                                        end if;
258
 
259
                        -- End of Transmission
260
                        when END_TX =>  -- Read Mode (for Next Phase)
261
                                                        if (mode(1) = SCCB_READ_MODE) then
262
                                                                next_state <= PREP_READ_PHASE;
263
 
264
                                                        else
265
                                                                next_state <= IDLE;
266
                                                        end if;
267
 
268
                        -- Prepare Read Phase
269
                        when PREP_READ_PHASE => next_state <= START_TX;
270
 
271
                        when others => next_state <= IDLE;
272
                end case;
273
        end process;
274
 
275
        ----------------------
276
        -- SCCB Bit Counter --
277
        ----------------------
278
        process(i_clock)
279
        begin
280
                if rising_edge(i_clock) then
281
 
282
                        -- Clock Enable
283
                        if (clock_enable = '1') then
284
 
285
                                -- Reset Counter
286
                                if (state = START_TX) or (bit_counter(3) = '1') then
287
                                        bit_counter <= (others => '0');
288
                                else
289
                                        bit_counter <= bit_counter +1;
290
                                end if;
291
                        end if;
292
        end if;
293
    end process;
294
 
295
        ----------------------------
296
        -- Slave Address Register --
297
        ----------------------------
298
        process(i_clock)
299
        begin
300
                if rising_edge(i_clock) then
301
 
302
                        -- Clock Enable
303
                        if (clock_enable = '1') then
304
 
305
                                -- Load Slave Address Input (Handle continuous left-shift)
306
                                if (state = IDLE) then
307
                                        slave_addr <= SCCB_WRITE_MODE & i_slave_addr;
308
 
309
                                -- Slave Address Read Mode (Handle continuous left-shift)
310
                                elsif (state = PREP_READ_PHASE) then
311
                                        slave_addr <= SCCB_READ_MODE & slave_addr(2 downto 0) & slave_addr(7 downto 4);
312
 
313
                                -- Left-Shift
314
                                else
315
                                        slave_addr <= slave_addr(6 downto 0) & slave_addr(7);
316
                                end if;
317
                        end if;
318
                end if;
319
        end process;
320
 
321
        -------------------------------
322
        -- Register Address Register --
323
        -------------------------------
324
        process(i_clock)
325
        begin
326
                if rising_edge(i_clock) then
327
 
328
                        -- Clock Enable
329
                        if (clock_enable = '1') then
330
 
331
                                -- Load Register Address Input (Handle continuous left-shift)
332
                                if (state = IDLE) then
333
                                        reg_addr <= i_reg_addr(1 downto 0) & i_reg_addr(7 downto 2);
334
 
335
                                -- Left-Shift
336
                                else
337
                                        reg_addr <= reg_addr(6 downto 0) & reg_addr(7);
338
                                end if;
339
                        end if;
340
                end if;
341
        end process;
342
 
343
        -----------------------------
344
        -- Register Value Register --
345
        -----------------------------
346
        process(i_clock)
347
        begin
348
                if rising_edge(i_clock) then
349
 
350
                        -- Clock Enable
351
                        if (clock_enable = '1') then
352
 
353
                                -- Load Register Value Input (Handle continuous left-shift)
354
                                if (state = IDLE) then
355
                                        reg_value <= i_reg_value(2 downto 0) & i_reg_value(7 downto 3);
356
 
357
                                -- Left-Shift
358
                                else
359
                                        reg_value <= reg_value(6 downto 0) & reg_value(7);
360
                                end if;
361
                        end if;
362
                end if;
363
        end process;
364
 
365
        -------------------
366
        -- Mode Register --
367
        -------------------
368
        process(i_clock)
369
        begin
370
                if rising_edge(i_clock) then
371
 
372
                        -- Clock Enable
373
                        if (clock_enable = '1') then
374
 
375
                                -- Load Mode Input
376
                                if (state = IDLE) then
377
                                        mode <= i_mode & SCCB_WRITE_MODE;
378
 
379
                                -- Right-Shift
380
                                elsif (state = END_TX) then
381
                                        mode <= SCCB_WRITE_MODE & mode(1);
382
                                end if;
383
                        end if;
384
                end if;
385
        end process;
386
 
387
        -----------------------
388
        -- SCCB Master Ready --
389
        -----------------------
390
        o_ready <= '1' when state = IDLE else '0';
391
 
392
        -----------------------
393
        -- SCCB SCL Register --
394
        -----------------------
395
        process(i_clock)
396
        begin
397
                if rising_edge(i_clock) then
398
 
399
                        -- Toggle SCL Reg
400
                        if (clock_enable_x2 = '1') then
401
                                scl_reg <= not(scl_reg);
402
                        end if;
403
                end if;
404
        end process;
405
 
406
        ---------------------
407
        -- SCCB SCL Enable --
408
        ---------------------
409
        scl_enable <= '0' when state = IDLE or state = START_TX or state = PREP_READ_PHASE else '1';
410
 
411
        --------------
412
        -- SCCB SCL --
413
        --------------
414
        -- ('0' or 'Z' values)
415
        o_scl <= '0' when scl_reg = '0' and scl_enable = '1' else 'Z';
416
 
417
        -----------------------
418
        -- SCCB SDA Selector --
419
        -----------------------
420
        sda_out <=      TRANSMISSION_START_BIT when state = START_TX or state = END_TX else
421
                                TRANSMISSION_DONT_CARE_BIT when bit_counter(3) = '1' else
422
                                slave_addr(7) when state = WRITE_SLAVE_ADDR else
423
                                reg_addr(7) when state = REGISTER_WRITE else
424
                                reg_value(7) when state = WRITE_REG_VALUE else
425
                                TRANSMISSION_DONT_CARE_BIT;
426
 
427
        ---------------------
428
        -- SCCB SDA Output --
429
        ---------------------
430
        -- ('0' or 'Z' values)
431
        io_sda <= '0' when sda_out = '0' else 'Z';
432
 
433
        ---------------------------
434
        -- SCCB SDA Input Enable --
435
        ---------------------------
436
        sda_in_enable <= '1' when (state = REGISTER_READ) and (bit_counter(3) = '0') else '0';
437
 
438
        --------------------------
439
        -- SCCB SDA Input Value --
440
        --------------------------
441
        process(i_clock)
442
        begin
443
                if rising_edge(i_clock) then
444
 
445
                        -- SDA Input Enable
446
                        if (clock_enable = '1') and (sda_in_enable = '1') then
447
                                sda_in_reg <= sda_in_reg(6 downto 0) & io_sda;
448
                        end if;
449
                end if;
450
        end process;
451
 
452
        ---------------------------
453
        -- SCCB Read Value Valid --
454
        ---------------------------
455
        process(i_clock)
456
        begin
457
                if rising_edge(i_clock) then
458
 
459
                        -- Disable SDA Valid Data (New cycle)
460
                        if (state = START_TX) then
461
                                sda_in_valid <= '0';
462
 
463
                        -- Read Value valid
464
                        elsif (mode(0) = SCCB_READ_MODE) and (state = END_TX) then
465
                                sda_in_valid <= '1';
466
                        end if;
467
                end if;
468
        end process;
469
        o_read_value_valid <= sda_in_valid;
470
 
471
        ---------------------
472
        -- SCCB Read Value --
473
        ---------------------
474
        o_read_value <= sda_in_reg when sda_in_valid = '1' else (others => '0');
475
 
476
end Behavioral;

powered by: WebSVN 2.1.0

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