Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393
Commits
74db68c1
Commit
74db68c1
authored
Oct 07, 2015
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more on sensor i2c
parent
2a260f5a
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
290 additions
and
292 deletions
+290
-292
x393_parameters.vh
includes/x393_parameters.vh
+7
-9
sensor_channel.v
sensor/sensor_channel.v
+14
-18
sensor_i2c.v
sensor/sensor_i2c.v
+113
-170
sensor_i2c_io.v
sensor/sensor_i2c_io.v
+13
-17
sensor_i2c_prot.v
sensor/sensor_i2c_prot.v
+107
-48
sensor_i2c_scl_sda.v
sensor/sensor_i2c_scl_sda.v
+16
-4
sensors393.v
sensor/sensors393.v
+14
-18
x393.v
x393.v
+6
-8
No files found.
includes/x393_parameters.vh
View file @
74db68c1
...
...
@@ -346,18 +346,16 @@
// sensor_i2c_io relative control register addresses
parameter SENSI2C_CTRL = 'h0,
// Control register bits
parameter SENSI2C_CMD_TABLE = 29, // [29]: 1 - write to translation table (ignore any other fields), 0 - write other fields
parameter SENSI2C_CMD_TAND = 28, // [28]: 1 - write table address (8 bits), 0 - write table data (28 bits)
parameter SENSI2C_CMD_RESET = 14, // [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
parameter SENSI2C_CMD_RUN = 13, // [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
parameter SENSI2C_CMD_RUN_PBITS = 1,
parameter SENSI2C_CMD_BYTES = 11, // if 1, use [10:9] to set command bytes to send after slave address (0..3)
parameter SENSI2C_CMD_BYTES_PBITS = 2,
parameter SENSI2C_CMD_DLY = 8, // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
parameter SENSI2C_CMD_DLY_PBITS = 8,
// direct control of SDA/SCL mutually exclusive with DLY control, disabled by running i2c
parameter SENSI2C_CMD_SCL = 16, // [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
parameter SENSI2C_CMD_SCL_WIDTH = 2,
parameter SENSI2C_CMD_SDA = 18, // [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA,
parameter SENSI2C_CMD_SDA_WIDTH = 2,
parameter SENSI2C_CMD_FIFO_RD = 3, // advane I2C read data FIFO by 1
parameter SENSI2C_CMD_ACIVE = 2, // [2] - SENSI2C_CMD_ACIVE_EARLY0, SENSI2C_CMD_ACIVE_SDA
parameter SENSI2C_CMD_ACIVE_EARLY0 = 1, // release SDA==0 early if next bit ==1
parameter SENSI2C_CMD_ACIVE_SDA = 0, // drive SDA=1 during the second half of SCL=1
parameter SENSI2C_STATUS = 'h1,
...
...
sensor/sensor_channel.v
View file @
74db68c1
...
...
@@ -62,18 +62,16 @@ module sensor_channel#(
// sensor_i2c_io relative control register addresses
parameter
SENSI2C_CTRL
=
'h0
,
// Control register bits
parameter
SENSI2C_CMD_TABLE
=
29
,
// [29]: 1 - write to translation table (ignore any other fields), 0 - write other fields
parameter
SENSI2C_CMD_TAND
=
28
,
// [28]: 1 - write table address (8 bits), 0 - write table data (28 bits)
parameter
SENSI2C_CMD_RESET
=
14
,
// [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
parameter
SENSI2C_CMD_RUN
=
13
,
// [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
parameter
SENSI2C_CMD_RUN_PBITS
=
1
,
parameter
SENSI2C_CMD_BYTES
=
11
,
// if 1, use [10:9] to set command bytes to send after slave address (0..3)
parameter
SENSI2C_CMD_BYTES_PBITS
=
2
,
parameter
SENSI2C_CMD_DLY
=
8
,
// [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
parameter
SENSI2C_CMD_DLY_PBITS
=
8
,
// direct control of SDA/SCL mutually exclusive with DLY control, disabled by running i2c
parameter
SENSI2C_CMD_SCL
=
16
,
// [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
parameter
SENSI2C_CMD_SCL_WIDTH
=
2
,
parameter
SENSI2C_CMD_SDA
=
18
,
// [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA,
parameter
SENSI2C_CMD_SDA_WIDTH
=
2
,
parameter
SENSI2C_CMD_FIFO_RD
=
3
,
// advane I2C read data FIFO by 1
parameter
SENSI2C_CMD_ACIVE
=
2
,
// [2] - SENSI2C_CMD_ACIVE_EARLY0, SENSI2C_CMD_ACIVE_SDA
parameter
SENSI2C_CMD_ACIVE_EARLY0
=
1
,
// release SDA==0 early if next bit ==1
parameter
SENSI2C_CMD_ACIVE_SDA
=
0
,
// drive SDA=1 during the second half of SCL=1
parameter
SENSI2C_STATUS
=
'h1
,
...
...
@@ -486,17 +484,15 @@ module sensor_channel#(
.
SENSI2C_CTRL
(
SENSI2C_CTRL
)
,
.
SENSI2C_STATUS
(
SENSI2C_STATUS
)
,
.
SENSI2C_STATUS_REG
(
SENSI2C_STATUS_REG
)
,
.
SENSI2C_CMD_TABLE
(
SENSI2C_CMD_TABLE
)
,
.
SENSI2C_CMD_TAND
(
SENSI2C_CMD_TAND
)
,
.
SENSI2C_CMD_RESET
(
SENSI2C_CMD_RESET
)
,
.
SENSI2C_CMD_RUN
(
SENSI2C_CMD_RUN
)
,
.
SENSI2C_CMD_RUN_PBITS
(
SENSI2C_CMD_RUN_PBITS
)
,
.
SENSI2C_CMD_BYTES
(
SENSI2C_CMD_BYTES
)
,
.
SENSI2C_CMD_BYTES_PBITS
(
SENSI2C_CMD_BYTES_PBITS
)
,
.
SENSI2C_CMD_DLY
(
SENSI2C_CMD_DLY
)
,
.
SENSI2C_CMD_DLY_PBITS
(
SENSI2C_CMD_DLY_PBITS
)
,
.
SENSI2C_CMD_SCL
(
SENSI2C_CMD_SCL
)
,
.
SENSI2C_CMD_SCL_WIDTH
(
SENSI2C_CMD_SCL_WIDTH
)
,
.
SENSI2C_CMD_SDA
(
SENSI2C_CMD_SDA
)
,
.
SENSI2C_CMD_SDA_WIDTH
(
SENSI2C_CMD_SDA_WIDTH
)
,
.
SENSI2C_CMD_FIFO_RD
(
SENSI2C_CMD_FIFO_RD
)
,
.
SENSI2C_CMD_ACIVE
(
SENSI2C_CMD_ACIVE
)
,
.
SENSI2C_CMD_ACIVE_EARLY0
(
SENSI2C_CMD_ACIVE_EARLY0
)
,
.
SENSI2C_CMD_ACIVE_SDA
(
SENSI2C_CMD_ACIVE_SDA
)
,
.
SENSI2C_DRIVE
(
SENSI2C_DRIVE
)
,
.
SENSI2C_IBUF_LOW_PWR
(
SENSI2C_IBUF_LOW_PWR
)
,
.
SENSI2C_IOSTANDARD
(
SENSI2C_IOSTANDARD
)
,
...
...
sensor/sensor_i2c.v
View file @
74db68c1
...
...
@@ -30,18 +30,16 @@ module sensor_i2c#(
parameter
SENSI2C_STATUS
=
'h1
,
parameter
SENSI2C_STATUS_REG
=
'h20
,
// Control register bits
parameter
SENSI2C_CMD_TABLE
=
29
,
// [29]: 1 - write to translation table (ignore any other fields), 0 - write other fields
parameter
SENSI2C_CMD_TAND
=
28
,
// [28]: 1 - write table address (8 bits), 0 - write table data (28 bits)
parameter
SENSI2C_CMD_RESET
=
14
,
// [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
parameter
SENSI2C_CMD_RUN
=
13
,
// [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
parameter
SENSI2C_CMD_RUN_PBITS
=
1
,
parameter
SENSI2C_CMD_BYTES
=
11
,
// if 1, use [10:9] to set command bytes to send after slave address (0..3)
parameter
SENSI2C_CMD_BYTES_PBITS
=
2
,
parameter
SENSI2C_CMD_DLY
=
8
,
// [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
parameter
SENSI2C_CMD_DLY_PBITS
=
8
,
parameter
SENSI2C_CMD_SCL
=
16
,
// [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
parameter
SENSI2C_CMD_SCL_WIDTH
=
2
,
parameter
SENSI2C_CMD_SDA
=
18
,
// [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA,
parameter
SENSI2C_CMD_SDA_WIDTH
=
2
parameter
SENSI2C_CMD_FIFO_RD
=
3
,
// advane I2C read data FIFO by 1
parameter
SENSI2C_CMD_ACIVE
=
2
,
// [2] - SENSI2C_CMD_ACIVE_EARLY0, SENSI2C_CMD_ACIVE_SDA
parameter
SENSI2C_CMD_ACIVE_EARLY0
=
1
,
// release SDA==0 early if next bit ==1
parameter
SENSI2C_CMD_ACIVE_SDA
=
0
// drive SDA=1 during the second half of SCL=1
)(
input
mrst
,
// @ posedge mclk
input
mclk
,
// global clock, half DDR3 clock, synchronizes all I/O through the command port
...
...
@@ -55,10 +53,8 @@ module sensor_i2c#(
output
status_rq
,
// input request to send status downstream
input
status_start
,
// Acknowledge of the first status packet byte (address)
input
frame_sync
,
// @posedge mclk increment/reset frame number
// input frame_0, // reset frame number to zero - can be done by soft reset before first enabled frame
// output busy, // busy (do not use software i2i)
input
scl_in
,
// i2c SCL input
input
sda_in
,
// i2c SDA input
input
scl_in
,
// i2c SCL input
output
scl_out
,
// i2c SCL output
output
sda_out
,
// i2c SDA output
output
scl_en
,
// i2c SCL enable
...
...
@@ -106,12 +102,16 @@ module sensor_i2c#(
reg
[
3
:
0
]
wpage_wr
;
// FIFO page where current write goes (reading from write address)
reg
[
1
:
0
]
wpage0_inc
;
// increment wpage0 (after frame sync or during reset)
reg
reset_cmd
;
reg
dly_cmd
;
reg
bytes_cmd
;
//
reg dly_cmd;
//
reg bytes_cmd;
reg
run_cmd
;
reg
twe
;
reg
active_cmd
;
reg
active_sda
;
reg
early_release_0
;
reg
reset_on
;
// reset FIFO in progress
reg
[
1
:
0
]
i2c_bytes
;
reg
[
7
:
0
]
i2c_dly
;
//
reg [1:0] i2c_bytes;
//
reg [7:0] i2c_dly;
reg
i2c_enrun
;
// enable i2c
reg
we_fifo_wp
;
// enable writing to fifo write pointer memory
reg
req_clr
;
// request for clearing fifo_wp (delay frame sync if previous is not yet sent out), also used for clearing all
...
...
@@ -136,49 +136,20 @@ module sensor_i2c#(
reg
[
5
:
0
]
rpointer
;
// FIFO read pointer for current page
reg
i2c_start
;
// initiate i2c register write sequence
reg
i2c_run
;
// i2c sequence is in progress
reg
i2c_done
;
// i2c sequence is over
reg
[
1
:
0
]
bytes_left
;
// bytes left to send after this one
reg
[
1
:
0
]
byte_number
;
// byte number to send next (3-2-1-0)
reg
[
1
:
0
]
byte_sending
;
// byte number currently sending (3-2-1-0)
reg
[
5
:
0
]
i2c_state
;
// 0x2b..0x28 - sending start, 0x27..0x24 - stop, 0x23..0x4 - data, 0x03..0x00 - ACKN
reg
[
7
:
0
]
dly_cntr
;
// bit delay down counter
reg
scl_hard
;
reg
sda_hard
;
reg
sda_en_hard
;
// reg wen_i2c_soft; // write software-contrlolles SDA, SCL state
reg
scl_en_soft
;
// software i2c control signals (used when i2c controller is disabled)
reg
scl_soft
;
reg
sda_en_soft
;
reg
sda_soft
;
wire
i2c_run
;
// i2c sequence is in progress (early end)
reg
i2c_run_d
;
// i2c sequence is in progress (early end)
// wire i2c_busy; // i2c sequence is in progress (until bus is free and stop finished)
wire
[
1
:
0
]
byte_number
;
// byte number to send next (3-2-1-0)
wire
[
1
:
0
]
seq_mem_re
;
wire
[
7
:
0
]
i2c_data
;
reg
[
8
:
0
]
i2c_sr
;
reg
i2c_dly_pre_over
;
wire
i2c_dly_pre2_over
;
reg
i2c_dly_over
;
wire
i2c_startseq_last
=
(
i2c_state
[
5
:
0
]
==
6'h28
)
;
wire
i2c_stopseq_last
=
(
i2c_state
[
5
:
0
]
==
6'h24
)
;
wire
i2c_dataseq_last
=
(
i2c_state
[
5
:
0
]
==
6'h00
)
;
wire
i2c_bit_last
=
(
i2c_state
[
1
:
0
]
==
2'h0
)
;
wire
i2c_is_ackn
=
(
i2c_state
[
5
:
2
]
==
4'h0
)
;
wire
i2c_is_start
=
i2c_state
[
5
]
&&
i2c_state
[
3
]
;
wire
i2c_is_stop
=
i2c_state
[
5
]
&&
i2c_state
[
2
]
;
wire
i2c_is_data
=
!
i2c_state
[
5
]
||
(
!
i2c_state
[
3
]
&&
!
i2c_state
[
2
])
;
// including ackn
// reg i2c_startseq_done; // last cycle of start sequence
reg
i2c_dataseq_done
;
// last cycle of each byte sequence
// reg i2c_dataseq_all_done; // last cycle of the last byte sequence
reg
[
2
:
0
]
i2c_byte_start
;
reg
i2c_sr_shift
;
reg
i2c_stop_start
;
reg
sda_0
;
reg
scl_0
;
wire
[
7
:
0
]
i2c_rdata
;
// data read over i2c bus
wire
i2c_rvalid
;
// i2c_rdata single-cycle strobe
wire
i2c_fifo_nempty
;
// i2c read fifo has data
reg
i2c_fifo_rd
;
// read i2c FIFO
reg
i2c_fifo_cntrl
;
// i2c FIFO odd/even byte
wire
[
7
:
0
]
i2c_fifo_dout
;
// i2c FIFO data out
reg
busy
;
reg
[
3
:
0
]
busy_cntr
;
assign
i2c_dly_pre2_over
=
(
dly_cntr
[
7
:
0
]
==
8'h2
)
;
wire
set_ctrl_w
;
wire
set_status_w
;
...
...
@@ -190,23 +161,17 @@ module sensor_i2c#(
assign
set_ctrl_w
=
we_cmd
&&
((
wa
&
~
SENSI2C_CTRL_MASK
)
==
SENSI2C_CTRL
)
;
// ==0
assign
set_status_w
=
we_cmd
&&
((
wa
&
~
SENSI2C_CTRL_MASK
)
==
SENSI2C_STATUS
)
;
// ==0
assign
scl_out
=
i2c_run
?
scl_hard
:
scl_soft
;
assign
sda_out
=
i2c_run
?
sda_hard
:
sda_soft
;
assign
scl_en
=
i2c_run
?
1'b1
:
scl_en_soft
;
assign
sda_en
=
i2c_run
?
sda_en_hard
:
sda_en_soft
;
assign
pre_wpage0_inc
=
(
!
wen
&&
!
(
|
wen_r
)
&&
!
wpage0_inc
[
0
])
&&
(
req_clr
||
reset_on
)
;
assign
fifo_wr_pointers_outw
=
fifo_wr_pointers_ram
[
wpage_wr
[
3
:
0
]]
;
// valid next after command
assign
fifo_wr_pointers_outr
=
fifo_wr_pointers_ram
[
page_r
[
3
:
0
]]
;
// wire we_abs;
// wire we_rel;
// wire we_cmd;
// wire [15:0] di;
// wire [3:0] wa;
assign
wen
=
set_ctrl_w
||
we_rel
||
we_abs
;
//remove set_ctrl_w?
assign
scl_en
=
i2c_enrun
;
reg
alive_fs
;
always
@
(
posedge
mclk
)
begin
if
(
set_status_w
)
alive_fs
<=
0
;
...
...
@@ -237,18 +202,36 @@ module sensor_i2c#(
status_generate
#(
.
STATUS_REG_ADDR
(
SENSI2C_STATUS_REG
)
,
.
PAYLOAD_BITS
(
7
+
3
)
// STATUS_PAYLOAD_BITS)
.
PAYLOAD_BITS
(
7
+
3
+
10
)
// STATUS_PAYLOAD_BITS)
)
status_generate_sens_i2c_i
(
.
rst
(
1'b0
)
,
// rst), // input
.
clk
(
mclk
)
,
// input
.
srst
(
mrst
)
,
// input
.
we
(
set_status_w
)
,
// input
.
wd
(
di
[
7
:
0
])
,
// input[7:0]
.
status
(
{
reset_on
,
req_clr
,
alive_fs
,
busy
,
frame_num
,
sda_in
,
scl_in
}
)
,
// input[25:0]
.
status
(
{
reset_on
,
req_clr
,
frame_num
[
3
:
0
]
,
alive_fs
,
busy
,
i2c_fifo_cntrl
,
i2c_fifo_nempty
,
i2c_fifo_dout
[
7
:
0
]
,
sda_in
,
scl_in
}
)
,
// input[25:0]
.
ad
(
status_ad
)
,
// output[7:0]
.
rq
(
status_rq
)
,
// output
.
start
(
status_start
)
// input
)
;
fifo_same_clock
#(
.
DATA_WIDTH
(
8
)
,
.
DATA_DEPTH
(
4
)
)
fifo_same_clock_i2c_rdata_i
(
.
rst
(
1'b0
)
,
// input
.
clk
(
mclk
)
,
// input
.
sync_rst
(
mrst
)
,
// input
.
we
(
i2c_rvalid
)
,
// input
.
re
(
i2c_fifo_rd
)
,
// input
.
data_in
(
i2c_rdata
)
,
// input[15:0]
.
data_out
(
i2c_fifo_dout
)
,
// output[15:0]
.
nempty
(
i2c_fifo_nempty
)
,
// output
.
half_full
()
// output reg
)
;
always
@
(
posedge
mclk
)
begin
if
(
wen
)
di_r
<=
di
;
// 32 bit command takes 6 cycles, so di_r can hold data for up to this long
...
...
@@ -268,32 +251,20 @@ module sensor_i2c#(
// wen_i2c_soft <= wen_d[0] && is_ctl;
// decoded commands, valid next cycle after we_*
reset_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_RESET
]
;
run_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_RUN
]
;
bytes_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_BYTES
]
;
dly_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_DLY
]
;
// direct i2c control, valid 1 cycle after we_*
if
(
i2c_run
)
scl_en_soft
<=
1'b0
;
else
if
(
set_ctrl_w
&&
!
di
[
SENSI2C_CMD_DLY
]
&&
|
di
[
SENSI2C_CMD_SCL
+:
SENSI2C_CMD_SCL_WIDTH
])
scl_en_soft
<=
(
di
[
SENSI2C_CMD_SCL
+:
SENSI2C_CMD_SCL_WIDTH
]
!=
2'h3
)
;
if
(
i2c_run
)
scl_soft
<=
1'b0
;
else
if
(
set_ctrl_w
&&
!
di
[
SENSI2C_CMD_DLY
]
&&
|
di
[
SENSI2C_CMD_SCL
+:
SENSI2C_CMD_SCL_WIDTH
])
scl_soft
<=
(
di
[
SENSI2C_CMD_SCL
+:
SENSI2C_CMD_SCL_WIDTH
]
==
2'h2
)
;
if
(
i2c_run
)
sda_en_soft
<=
1'b0
;
else
if
(
set_ctrl_w
&&
!
di
[
SENSI2C_CMD_DLY
]
&&
|
di
[
SENSI2C_CMD_SDA
+:
SENSI2C_CMD_SDA_WIDTH
])
sda_en_soft
<=
(
di
[
SENSI2C_CMD_SDA
+:
SENSI2C_CMD_SDA_WIDTH
]
!=
2'h3
)
;
if
(
i2c_run
)
sda_soft
<=
1'b0
;
else
if
(
set_ctrl_w
&&
!
di
[
SENSI2C_CMD_DLY
]
&&
|
di
[
SENSI2C_CMD_SDA
+:
SENSI2C_CMD_SDA_WIDTH
])
sda_soft
<=
(
di
[
SENSI2C_CMD_SDA
+:
SENSI2C_CMD_SDA_WIDTH
]
==
2'h2
)
;
// setting i2c control parameters, valid 2 cycles after we_*
if
(
bytes_cmd
)
i2c_bytes
[
1
:
0
]
<=
di_r
[
SENSI2C_CMD_BYTES
-
1
-:
SENSI2C_CMD_BYTES_PBITS
]
;
//[10:9];
if
(
dly_cmd
)
i2c_dly
[
7
:
0
]
<=
di_r
[
SENSI2C_CMD_DLY
-
1
-:
SENSI2C_CMD_DLY_PBITS
]
;
//[ 7:0];
if
(
reset_cmd
)
i2c_enrun
<=
1'b0
;
reset_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_RESET
]
&&
!
di
[
SENSI2C_CMD_TABLE
]
;
run_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_RUN
]
&&
!
di
[
SENSI2C_CMD_TABLE
]
;
active_cmd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_ACIVE
]
&&
!
di
[
SENSI2C_CMD_TABLE
]
;
twe
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_TABLE
]
;
i2c_fifo_rd
<=
set_ctrl_w
&&
di
[
SENSI2C_CMD_FIFO_RD
]
&&
!
di
[
SENSI2C_CMD_TABLE
]
;
if
(
reset_cmd
||
mrst
)
i2c_enrun
<=
1'b0
;
else
if
(
run_cmd
)
i2c_enrun
<=
di_r
[
SENSI2C_CMD_RUN
-
1
-:
SENSI2C_CMD_RUN_PBITS
]
;
// [12];
if
(
active_cmd
)
begin
early_release_0
<=
di_r
[
SENSI2C_CMD_ACIVE_EARLY0
]
;
active_sda
<=
di_r
[
SENSI2C_CMD_ACIVE_SDA
]
;
end
// write pointer memory
wpage0_inc
<=
{
wpage0_inc
[
0
]
,
pre_wpage0_inc
};
// reset pointers in all 16 pages:
...
...
@@ -313,31 +284,16 @@ module sensor_i2c#(
else
if
(
we_rel
)
wpage_wr
<=
wpage0
+
wa
;
else
if
(
wpage0_inc
[
0
])
wpage_wr
<=
wpage_prev
;
// only for erasing?
// we_fifo_wp <= wen || wpage0_inc; // during commands and during reset?
/// we_fifo_wp <= wen_fifo[0] || wpage0_inc; // during commands and during reset?
// we_fifo_wp <= wen_fifo[0] || we_rel || we_abs; // ??
//// we_fifo_wp <= wen_fifo || we_rel || we_abs; // ??
we_fifo_wp
<=
wen_fifo
||
wpage0_inc
[
0
]
;
// reg [1:0] wen_r;
// reg [1:0] wen_fifo;
// if (wen_fifo[0]) fifo_wr_pointers_outw_r[5:0] <= fifo_wr_pointers_outw[5:0];
if
(
wen_fifo
)
fifo_wr_pointers_outw_r
[
5
:
0
]
<=
fifo_wr_pointers_outw
[
5
:
0
]
;
// write to dual-port pointer memory
if
(
we_fifo_wp
)
fifo_wr_pointers_ram
[
wpage_wr
]
<=
wpage0_inc
[
1
]
?
6'h0
:
(
fifo_wr_pointers_outw_r
[
5
:
0
]
+
1
)
;
fifo_wr_pointers_outr_r
[
5
:
0
]
<=
fifo_wr_pointers_outr
[
5
:
0
]
;
// just register distri
// command i2c fifo (RAMB16_S9_S18)
// if (wen_fifo[0]) i2c_cmd_wa <= {wpage_wr[3:0],fifo_wr_pointers_outw[5:0]};
if
(
wen_fifo
)
i2c_cmd_wa
<=
{
wpage_wr
[
3
:
0
]
,
fifo_wr_pointers_outw
[
5
:
0
]
};
// if (wen_d[1]) i2c_cmd_wa[10:1] <= {wpage_wr[3:0],fifo_wr_pointers_outw[5:0]};
// i2c_cmd_wa[0] <= !wen_d[1]; // 0 for the first in a pair, 1 - for the second
// i2c_cmd_we <= !reset_cmd && (wen_d[1] || (i2c_cmd_we && !wen_d[3])); //reset_cmd added to keep simulator happy
i2c_cmd_we
<=
!
reset_cmd
&&
wen_fifo
;
// [0];
// signals related to reading from i2c FIFO
...
...
@@ -346,60 +302,14 @@ module sensor_i2c#(
if
(
reset_cmd
||
page_r_inc
[
0
])
rpointer
[
5
:
0
]
<=
6'h0
;
else
if
(
i2c_
done
)
rpointer
[
5
:
0
]
<=
rpointer
[
5
:
0
]
+
1
;
else
if
(
i2c_
run_d
&&
!
i2c_run
)
rpointer
[
5
:
0
]
<=
rpointer
[
5
:
0
]
+
1
;
i2c_run
<=
!
reset_cmd
&&
!
reset_on
&&
(
i2c_start
||
(
i2c_run
&&
!
i2c_done
))
;
i2c_start
<=
i2c_enrun
&&
!
i2c_run
&&
!
i2c_start
&&
(
rpointer
[
5
:
0
]
!=
fifo_wr_pointers_outr_r
[
5
:
0
])
&&
!
(
|
page_r_inc
)
;
page_r_inc
[
1
:
0
]
<=
{
page_r_inc
[
0
]
,
!
i2c_run
&&
// not i2c in progress
!
page_r_inc
[
0
]
&&
// was not incrementing in previous cycle
(
rpointer
==
fifo_wr_pointers_outr_r
)
&&
// nothing left for this page
(
page_r
!=
wpage0
)
};
// not already the write-open current page
//i2c sequence generation
if
(
!
i2c_run
)
bytes_left
[
1
:
0
]
<=
i2c_bytes
[
1
:
0
]
;
else
if
(
i2c_dataseq_done
)
bytes_left
[
1
:
0
]
<=
bytes_left
[
1
:
0
]
-
1
;
if
(
!
i2c_run
)
byte_sending
[
1
:
0
]
<=
2'h3
;
else
if
(
i2c_dataseq_done
)
byte_sending
[
1
:
0
]
<=
byte_sending
[
1
:
0
]
+
1
;
if
(
!
i2c_run
)
byte_number
[
1
:
0
]
<=
2'h3
;
else
if
(
i2c_byte_start
[
2
])
byte_number
[
1
:
0
]
<=
byte_number
[
1
:
0
]
-
1
;
if
(
!
i2c_run
||
i2c_dly_over
)
dly_cntr
[
7
:
0
]
<=
i2c_dly
[
7
:
0
]
;
else
dly_cntr
[
7
:
0
]
<=
dly_cntr
[
7
:
0
]
-
1
;
i2c_dly_pre_over
<=
i2c_dly_pre2_over
;
// period = 3..258
i2c_dly_over
<=
i2c_dly_pre_over
;
i2c_dataseq_done
<=
i2c_dataseq_last
&&
i2c_dly_pre_over
;
i2c_byte_start
[
2
:
0
]
<=
{
i2c_byte_start
[
1
:
0
]
,
(
i2c_startseq_last
||
(
i2c_dataseq_last
&&
(
bytes_left
[
1
:
0
]
!=
2'h0
)))
&&
i2c_dly_pre2_over
};
i2c_sr_shift
<=
i2c_bit_last
&&
!
(
i2c_dataseq_last
)
&&
i2c_dly_pre_over
;
i2c_stop_start
<=
i2c_dataseq_last
&&
(
bytes_left
[
1
:
0
]
==
2'h0
)
&&
i2c_dly_pre_over
;
i2c_done
<=
i2c_stopseq_last
&&
i2c_dly_pre_over
;
if
(
i2c_byte_start
[
2
])
i2c_sr
[
8
:
0
]
<=
{
i2c_data
[
7
:
0
]
,
1'b1
};
else
if
(
i2c_sr_shift
)
i2c_sr
[
8
:
0
]
<=
{
i2c_sr
[
7
:
0
]
,
1'b1
};
if
(
!
i2c_run
)
i2c_state
[
5
:
0
]
<=
6'h2a
;
// start of start seq
else
if
(
i2c_stop_start
)
i2c_state
[
5
:
0
]
<=
6'h26
;
// start of stop seq
else
if
(
i2c_byte_start
[
2
])
i2c_state
[
5
:
0
]
<=
6'h23
;
// start of data seq
else
if
(
i2c_dly_over
)
i2c_state
[
5
:
0
]
<=
i2c_state
[
5
:
0
]
-
1
;
// now creating output signals
scl_0
<=
(
i2c_is_start
&&
(
i2c_state
[
1
:
0
]
!=
2'h0
))
||
(
i2c_is_stop
&&
!
i2c_state
[
1
])
||
(
i2c_is_data
&&
(
i2c_state
[
1
]
^
i2c_state
[
0
]))
||
!
i2c_run
;
sda_0
<=
(
i2c_is_start
&&
i2c_state
[
1
])
||
(
i2c_is_stop
&&
(
i2c_state
[
1
:
0
]
==
2'h0
))
||
(
i2c_is_data
&&
i2c_sr
[
8
])
||
!
i2c_run
;
sda_hard
<=
sda_0
;
scl_hard
<=
scl_0
;
sda_en_hard
<=
i2c_run
&&
(
!
sda_0
||
(
!
i2c_is_ackn
&&
!
sda_hard
))
;
if
(
wen
)
busy_cntr
<=
4'hf
;
else
if
(
|
busy_cntr
)
busy_cntr
<=
busy_cntr
-
1
;
...
...
@@ -407,22 +317,55 @@ module sensor_i2c#(
(
|
busy_cntr
)
||
i2c_run
||
reset_on
;
i2c_run_d
<=
i2c_run
;
if
(
mrst
)
i2c_fifo_cntrl
<=
0
;
else
if
(
i2c_fifo_rd
)
i2c_fifo_cntrl
<=
~
i2c_fifo_cntrl
;
end
sensor_i2c_prot
sensor_i2c_prot_i
(
.
mrst
(
mrst
)
,
// input
.
mclk
(
mclk
)
,
// input
.
i2c_rst
(
reset_cmd
)
,
// input
.
i2c_start
(
i2c_start
)
,
// input
.
active_sda
(
active_sda
)
,
// input
.
early_release_0
(
early_release_0
)
,
// input
.
tand
(
di_r
[
SENSI2C_CMD_TAND
])
,
// input
.
td
(
di_r
[
SENSI2C_CMD_TAND
-
1
:
0
])
,
// input[27:0]
.
twe
(
twe
)
,
// input
.
sda_in
(
sda_in
)
,
// input
.
sda
(
sda_out
)
,
// output
.
sda_en
(
sda_en
)
,
// output
.
scl
(
scl_out
)
,
// output
.
i2c_run
(
i2c_run
)
,
// output reg
.
i2c_busy
()
,
//i2c_busy), // output reg
.
seq_mem_ra
(
byte_number
)
,
// output[1:0] reg
.
seq_mem_re
(
seq_mem_re
)
,
// output[1:0]
.
seq_rd
(
i2c_data
)
,
// input[7:0]
.
rdata
(
i2c_rdata
)
,
// output[7:0]
.
rvalid
(
i2c_rvalid
)
// output
)
;
ram_var_w_var_r
#(
.
REGISTERS
(
1
)
,
// try to delay i2c_byte_start by one more cycle
.
LOG2WIDTH_WR
(
5
)
,
.
LOG2WIDTH_RD
(
3
)
)
i_fifo
(
.
rclk
(
mclk
)
,
// input
.
raddr
(
{
page_r
[
3
:
0
]
,
rpointer
[
5
:
0
]
,
byte_number
[
1
:
0
]
}
)
,
// input[11:0]
.
ren
(
i2c_byte_start
[
0
])
,
// input
.
regen
(
i2c_byte_start
[
1
])
,
// input
.
data_out
(
i2c_data
[
7
:
0
])
,
// output[7:0]
.
wclk
(
mclk
)
,
// input
.
waddr
(
i2c_cmd_wa
)
,
// input[9:0]
.
we
(
i2c_cmd_we
)
,
// input
.
web
(
8'hff
)
,
// input[7:0]
.
data_in
(
di_r
)
// input[31:0]
.
rclk
(
mclk
)
,
// input
.
raddr
(
{
page_r
[
3
:
0
]
,
rpointer
[
5
:
0
]
,
byte_number
[
1
:
0
]
}
)
,
// input[11:0]
.
ren
(
seq_mem_re
[
0
])
,
// input
.
regen
(
seq_mem_re
[
1
])
,
// input
.
data_out
(
i2c_data
[
7
:
0
])
,
// output[7:0]
.
wclk
(
mclk
)
,
// input
.
waddr
(
i2c_cmd_wa
)
,
// input[9:0]
.
we
(
i2c_cmd_we
)
,
// input
.
web
(
8'hff
)
,
// input[7:0]
.
data_in
(
di_r
)
// input[31:0]
)
;
endmodule
...
...
sensor/sensor_i2c_io.v
View file @
74db68c1
...
...
@@ -30,18 +30,16 @@ module sensor_i2c_io#(
parameter
SENSI2C_STATUS
=
'h1
,
parameter
SENSI2C_STATUS_REG
=
'h20
,
// Control register bits
parameter
SENSI2C_CMD_TABLE
=
29
,
// [29]: 1 - write to translation table (ignore any other fields), 0 - write other fields
parameter
SENSI2C_CMD_TAND
=
28
,
// [28]: 1 - write table address (8 bits), 0 - write table data (28 bits)
parameter
SENSI2C_CMD_RESET
=
14
,
// [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
parameter
SENSI2C_CMD_RUN
=
13
,
// [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
parameter
SENSI2C_CMD_RUN_PBITS
=
1
,
parameter
SENSI2C_CMD_BYTES
=
11
,
// if 1, use [10:9] to set command bytes to send after slave address (0..3)
parameter
SENSI2C_CMD_BYTES_PBITS
=
2
,
parameter
SENSI2C_CMD_DLY
=
8
,
// [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
parameter
SENSI2C_CMD_DLY_PBITS
=
8
,
// direct control of SDA/SCL mutually exclusive with DLY control, disabled by running i2c
parameter
SENSI2C_CMD_SCL
=
16
,
// [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
parameter
SENSI2C_CMD_SCL_WIDTH
=
2
,
parameter
SENSI2C_CMD_SDA
=
18
,
// [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA,
parameter
SENSI2C_CMD_SDA_WIDTH
=
2
,
parameter
SENSI2C_CMD_FIFO_RD
=
3
,
// advane I2C read data FIFO by 1
parameter
SENSI2C_CMD_ACIVE
=
2
,
// [2] - SENSI2C_CMD_ACIVE_EARLY0, SENSI2C_CMD_ACIVE_SDA
parameter
SENSI2C_CMD_ACIVE_EARLY0
=
1
,
// release SDA==0 early if next bit ==1
parameter
SENSI2C_CMD_ACIVE_SDA
=
0
,
// drive SDA=1 during the second half of SCL=1
// I/O parameters
parameter
integer
SENSI2C_DRIVE
=
12
,
parameter
SENSI2C_IBUF_LOW_PWR
=
"TRUE"
,
...
...
@@ -75,17 +73,15 @@ module sensor_i2c_io#(
.
SENSI2C_CTRL
(
SENSI2C_CTRL
)
,
.
SENSI2C_STATUS
(
SENSI2C_STATUS
)
,
.
SENSI2C_STATUS_REG
(
SENSI2C_STATUS_REG
)
,
.
SENSI2C_CMD_TABLE
(
SENSI2C_CMD_TABLE
)
,
.
SENSI2C_CMD_TAND
(
SENSI2C_CMD_TAND
)
,
.
SENSI2C_CMD_RESET
(
SENSI2C_CMD_RESET
)
,
.
SENSI2C_CMD_RUN
(
SENSI2C_CMD_RUN
)
,
.
SENSI2C_CMD_RUN_PBITS
(
SENSI2C_CMD_RUN_PBITS
)
,
.
SENSI2C_CMD_BYTES
(
SENSI2C_CMD_BYTES
)
,
.
SENSI2C_CMD_BYTES_PBITS
(
SENSI2C_CMD_BYTES_PBITS
)
,
.
SENSI2C_CMD_DLY
(
SENSI2C_CMD_DLY
)
,
.
SENSI2C_CMD_DLY_PBITS
(
SENSI2C_CMD_DLY_PBITS
)
,
.
SENSI2C_CMD_SCL
(
SENSI2C_CMD_SCL
)
,
.
SENSI2C_CMD_SCL_WIDTH
(
SENSI2C_CMD_SCL_WIDTH
)
,
.
SENSI2C_CMD_SDA
(
SENSI2C_CMD_SDA
)
,
.
SENSI2C_CMD_SDA_WIDTH
(
SENSI2C_CMD_SDA_WIDTH
)
.
SENSI2C_CMD_FIFO_RD
(
SENSI2C_CMD_FIFO_RD
)
,
.
SENSI2C_CMD_ACIVE
(
SENSI2C_CMD_ACIVE
)
,
.
SENSI2C_CMD_ACIVE_EARLY0
(
SENSI2C_CMD_ACIVE_EARLY0
)
,
.
SENSI2C_CMD_ACIVE_SDA
(
SENSI2C_CMD_ACIVE_SDA
)
)
sensor_i2c_i
(
.
mrst
(
mrst
)
,
// input
...
...
sensor/sensor_i2c_prot.v
View file @
74db68c1
...
...
@@ -25,41 +25,76 @@ module sensor_i2c_prot(
input
mclk
,
// global clock
input
i2c_rst
,
input
i2c_start
,
input
[
7
:
0
]
i2c_dly
,
// bit duration-1 (>=2?), 1 unit - 4 mclk periods
input
active_sda
,
// global config bit: active pull SDA
input
early_release_0
,
// global config bit: release SDA immediately after end of SCL if next bit is 1 (for ACKN). Data hold time by slow 0->1
// setup LUT to translate address page into SA, actual address MSB and number of bytes to write (second word bypasses translation)
input
tand
,
// table address/not data
input
[
19
:
0
]
td
,
// table address/data in
input
[
27
:
0
]
td
,
// table address/data in
input
twe
,
// table write enable
input
sda_in
,
// data from sda pad
output
reg
sda
,
output
reg
sda_en
,
output
reg
scl
,
output
i2c_run
,
output
sda
,
output
sda_en
,
output
scl
,
output
reg
i2c_run
,
// released as soon as the last command (usually STOP) gets to the i2c start/stop/shift module
output
reg
i2c_busy
,
// released when !i2c_run and all i2c activity is over
output
reg
[
1
:
0
]
seq_mem_ra
,
// number of byte to read from the sequencer memory
output
[
1
:
0
]
seq_mem_re
,
// [0] - re, [1] - regen to teh sequencer memory
input
[
7
:
0
]
seq_rd
,
// data from the sequencer memory
output
[
7
:
0
]
rdata
,
output
rvalid
)
;
/*
Sequencer provides 4 bytes per command, read one byte at a time as seq_rd[7:0] with byte address provided by seq_mem_ra[1:0],
seq_mem_re[0] external memory re, seq_mem_re[1] - regen
MSB (byte 3) is used as index in the table that provides for register writes (tdout[8] == 0):
high byte of the register address (if used) - tdout[7:0]
slave address - tdout[15:9],
number of bytes to send after SA - tdout[19:16] (includes both adderss and data bytes, aligned to the MSB)
bit delay - tdout[27:20] (periods of mclk for 1/4 of the SCL period), should be >2(?)
if number of bytes to send (including address) >4, there will be no stop and the next command will bypass MSB decoding through table
and be sent out as data bytes (MSB first, aligned to the LSB (byte[0]), so if only one byte is to be sent bytes[3:1] will be skipped.
In read mode (tdout[8] == 1) it is possible to use 1 or 2 byte register address and read 1..8 bytes
bit delay - tdout[27:20] (same as for register writes - see above)
Slave address in the read mode is provided as byte[2], register adderss in bytes[1:0] (byte[1] is skipped for 1-byte addresses)
Number of data bytes to read is provided as tdout[18:16], with 0 meaning 8 bytes
Nuber of register address bytes is defined by tdout[19]: 0 - one byte, 1 - 2 bytes address
"active_sda" (configuration bit enables active pull-up on SDA line by the master for faster communication, it is active during second
half of the SCL=0 for the data bits and also for the first interval of the RESTART sequence and for the last of the STOP one.
"early_release_0" - when sending data bit "0" over the SDA line, release SDA=0 immediately after SCL: 1->0 if the next bit to send is "1".
This is OK as the SDA 0->1 transition will be slower than SCL 1->0 (only pulled up by a resistor), so there will be positive hold time
on SDA line. This is done so for communications with 10359 (or similar) board where FPGA can also actively drive SDA line for faster
communication.
Active driving of the SDA line increases only master send communication, so ACKN may be missed, but it is not used in this implementation.
Reading registers is less used operation than write and can use slower communication spped (provided through the table)
*/
reg
[
7
:
0
]
twa
;
wire
[
31
:
0
]
tdout
;
reg
[
7
:
0
]
reg_ah
;
// MSB of the register address (instead of the byte 2)
reg
[
7
:
0
]
slave_a_rah
;
// 8-bit slave address , used instead of the byte 3, later replaced with reg_ah
reg
[
3
:
0
]
num_bytes_send
;
// number of bytes to send (if more than 4 will skip stop and continue with next data
reg
[
7
:
0
]
i2c_dly
;
// bit duration-1 (>=2?), 1 unit - 4 mclk periods
reg
[
3
:
0
]
bytes_left_send
;
// Number of bytes left in register write sequence (not counting sa?)
reg
[
6
:
0
]
run_reg_wr
;
// run register write [6] - start, [5] - send sa, [4] - send high byte (from table),..[0] - send stop
reg
[
4
:
0
]
run_extra_wr
;
// continue register write (if more than sa + 4bytes) [4] - byte 3, .. [1]- byte0, [0] - stop
reg
run_extra_wr_d
;
// any of run_extra_wr bits, delayed by 1
reg
[
7
:
0
]
run_reg_rd
;
// [7] - start, [6] SA (byte 3), [5] (optional) - RA_msb, [4] - RA_lsb, [3] - restart, [2] - SA, [1] - read bytes, [0] - stop
reg
i2c_done
;
wire
i2c_next_byte
;
reg
run_extra_wr_d
;
// any of run_extra_wr bits, delayed by 1
reg
run_any_d
;
// any of command states, delayed by 1
reg
[
1
:
0
]
pre_cmd
;
// from i2c_start until run_any_d will be active
// reg i2c_done;
// wire i2c_next_byte;
reg
[
2
:
0
]
mem_re
;
reg
mem_valid
;
reg
[
3
:
0
]
table_re
;
reg
read_mem_msb
;
wire
decode_reg_rd
=
&
seq_rd
[
7
:
4
]
;
wire
start_wr_seq_w
=
!
run_extra_wr_d
&&
!
decode_reg_rd
&&
read_mem_msb
;
// reg read_mem_msb;
// wire decode_reg_rd = &seq_rd[7:4];
// wire start_wr_seq_w = !run_extra_wr_d && !decode_reg_rd && read_mem_msb;
wire
start_wr_seq_w
=
table_re
[
2
]
&&
!
tdout
[
8
]
;
wire
start_rd_seq_w
=
table_re
[
2
]
&&
tdout
[
8
]
;
wire
start_extra_seq_w
=
i2c_start
&&
(
bytes_left_send
!=
0
)
;
wire
snd_start_w
=
run_reg_wr
[
6
]
||
1'b0
;
// add start & restart of read
wire
snd_stop_w
=
run_reg_wr
[
0
]
||
1'b0
;
// add stop of read
...
...
@@ -78,9 +113,8 @@ module sensor_i2c_prot(
send_sa_rah
|
send_rd
,
send_rd_sa
|
send_rd
};
reg
[
8
:
0
]
sr_in
;
// input data for the shift register
wire
bus_busy
;
// i2c bus is active
wire
bus_open
;
// i2c bus is "open" (START-ed but not STOP-ed) - between multi-byte write if it spans >1 32-bit comands
wire
i2c_rdy
;
reg
next_cmd
;
// i2c command (start/stop/data) accepted, proceed to the next stage
...
...
@@ -93,20 +127,38 @@ module sensor_i2c_prot(
reg
[
1
:
0
]
initial_address
;
// initial data byte to read: usually 3 but for extra write may be different
wire
[
3
:
0
]
initial_address_w
=
bytes_left_send
-
1
;
// if bytes left to send == 0 - will be 3
wire
unused
;
// unused ackn signal
wire
unused
;
// unused ackn signal SuppressThisWarning VEditor
wire
pre_table_re
=
!
run_extra_wr_d
&&
(
&
seq_mem_ra
[
1
:
0
])
&&
mem_re
[
1
]
;
assign
seq_mem_re
=
mem_re
[
1
:
0
]
;
always
@
(
posedge
mclk
)
begin
run_extra_wr_d
<=
|
run_extra_wr
;
read_mem_msb
<=
mem_re
[
1
]
&&
(
seq_mem_ra
==
3
)
;
// reading sequencer data MSB - change to other one-hot?
table_re
<=
{
table_re
[
2
:
0
]
,
start_wr_seq_w
};
run_any_d
<=
(
|
run_reg_wr
)
||
(
|
run_extra_wr
)
||
(
|
run_reg_rd
)
;
if
(
mrst
||
i2c_rst
)
pre_cmd
<=
0
;
else
if
(
i2c_start
)
pre_cmd
<=
1
;
else
if
(
run_any_d
)
pre_cmd
<=
0
;
if
(
mrst
||
i2c_rst
)
i2c_run
<=
0
;
else
i2c_run
<=
i2c_start
||
pre_cmd
||
run_any_d
;
if
(
mrst
||
i2c_rst
)
i2c_busy
<=
0
;
else
i2c_busy
<=
i2c_start
||
pre_cmd
||
run_any_d
||
bus_busy
||
bus_open
;
table_re
<=
{
table_re
[
2
:
0
]
,
pre_table_re
};
// start_wr_seq_w};
if
(
table_re
[
2
])
begin
reg_ah
<=
tdout
[
7
:
0
]
;
// MSB of the register address (instead of the byte 2)
num_bytes_send
<=
tdout
[
19
:
16
]
;
// number of bytes to send (if more than 4 will skip stop and continue with next data
i2c_dly
<=
tdout
[
27
:
20
]
;
end
if
(
table_re
[
2
])
slave_a_rah
<=
{
tdout
[
1
4
:
8
]
,
1'b0
};
if
(
table_re
[
2
])
slave_a_rah
<=
{
tdout
[
1
5
:
9
]
,
1'b0
};
else
if
(
next_cmd
&&
run_reg_wr
[
6
])
slave_a_rah
<=
reg_ah
;
// will copy even if not used
next_cmd
<=
pre_next_cmd
;
...
...
@@ -137,7 +189,7 @@ module sensor_i2c_prot(
};
// send just bytes (up to 4), stop if nothing left
if
(
mrst
||
i2c_rst
)
run_extra_wr
<=
0
;
else
if
(
i2c_start
&&
(
bytes_left_send
!=
0
))
run_extra_wr
<=
{
else
if
(
start_extra_seq_w
)
run_extra_wr
<=
{
|
bytes_left_send
[
3
:
2
]
,
// >= 4 bytes left
(
bytes_left_send
==
3
)
,
// exactly 3 bytes left
(
bytes_left_send
==
2
)
,
// exactly 2 bytes left
...
...
@@ -154,13 +206,18 @@ module sensor_i2c_prot(
// reg [ 7:0] run_reg_rd; // [7] - start, [6] SA (byte 3), [5] (optional) - RA_msb, [4] - RA_lsb, [3] - restart, [2] - SA, [1] - read bytes, [0] - stop
if
(
!
run_extra_wr
&&
decode_reg_rd
&&
read_mem_msb
)
read_address_bytes
<=
seq_rd
[
3
]
;
// if (!run_extra_wr && decode_reg_rd && read_mem_msb) read_address_bytes <= seq_rd[3];
// if (!run_extra_wr && decode_reg_rd && read_mem_msb) read_data_bytes <= seq_rd[2:0];
if
(
table_re
[
2
]
&&
tdout
[
8
])
read_address_bytes
<=
tdout
[
19
]
;
if
(
!
run_extra_wr
&&
decode_reg_rd
&&
read_mem_msb
)
read_data_bytes
<=
seq_rd
[
2
:
0
]
;
if
(
table_re
[
2
]
&&
tdout
[
8
])
read_data_bytes
<=
tdout
[
18
:
16
]
;
else
if
(
run_reg_rd
[
1
]
&&
next_cmd
)
read_data_bytes
<=
read_data_bytes
-
1
;
// read i2c data
if
(
mrst
||
i2c_rst
)
run_reg_rd
<=
0
;
else
if
(
!
run_extra_wr_d
&&
decode_reg_rd
&&
read_mem_msb
)
run_reg_rd
<=
8'h80
;
// else if (!run_extra_wr_d && decode_reg_rd && read_mem_msb) run_reg_rd <= 8'h80;
else
if
(
start_rd_seq_w
)
run_reg_rd
<=
8'h80
;
else
if
(
next_cmd
)
run_reg_rd
<=
{
1'b0
,
// first "start"
run_reg_rd
[
7
]
,
// slave_addr - always after start (bit0 = 0)
run_reg_rd
[
6
]
&
read_address_bytes
,
// optional MSB of the register address
...
...
@@ -207,21 +264,23 @@ module sensor_i2c_prot(
.
mclk
(
mclk
)
,
// input
.
i2c_rst
(
i2c_rst
)
,
// input
.
i2c_dly
(
i2c_dly
)
,
// input[7:0]
.
active_sda
(
active_sda
)
,
// input
.
early_release_0
(
early_release_0
)
,
// input
.
snd_start
(
snd_start
)
,
// input
.
snd_stop
(
snd_stop
)
,
// input
.
snd9
(
snd9
)
,
// input
.
din
(
sr_in
)
,
// input[8:0]
.
dout
(
{
rdata
,
unused
}
)
,
// output[8:0]
.
dout_stb
(
rvalid
)
,
// output reg
.
scl
()
,
// output reg
.
scl
(
scl
)
,
// output reg
.
sda_in
(
sda_in
)
,
// input
.
sda
()
,
// output reg
.
sda
(
sda
)
,
// output reg
.
sda_en
(
sda_en
)
,
// output reg
.
ready
(
i2c_rdy
)
,
// output register
.
bus_busy
()
,
// output reg
.
is_open
()
// output
.
bus_busy
(
bus_busy
)
,
// output reg
.
is_open
(
bus_open
)
// output
)
;
// table write
always
@
(
posedge
mclk
)
begin
if
(
mrst
)
twa
<=
0
;
...
...
@@ -243,7 +302,7 @@ module sensor_i2c_prot(
.
waddr
(
{
1'b0
,
twa
}
)
,
// input[8:0]
.
we
(
twe
&&
!
tand
)
,
// input
.
web
(
4'hf
)
,
// input[3:0]
.
data_in
(
{
12
'b0
,
td
}
)
// input[31:0]
.
data_in
(
{
4
'b0
,
td
}
)
// input[31:0]
)
;
...
...
sensor/sensor_i2c_scl_sda.v
View file @
74db68c1
...
...
@@ -25,15 +25,19 @@ module sensor_i2c_scl_sda(
input
mclk
,
// global clock
input
i2c_rst
,
input
[
7
:
0
]
i2c_dly
,
// bit duration-1 (>=2?), 1 unit - 4 mclk periods
input
active_sda
,
// active pull SDA
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
input
snd_start
,
input
snd_stop
,
input
snd9
,
// input rcv, // recieve mode (valid with snd9) - master receives, slave - sends
input
[
8
:
0
]
din
,
output
[
8
:
0
]
dout
,
//
output
reg
dout_stb
,
// dout contains valid data
output
reg
scl
,
// i2c SCL signal
input
sda_in
,
// i2c SDA signal form I/O pad
output
reg
sda
,
// i2c SDA signal
output
reg
sda_en
,
// drive SDA when SDA=0 and during second half of SCL = 0 interval (also during stop)
output
ready
,
// ready to accept commands
output
reg
bus_busy
,
// i2c bus busy (1 cycle behind !ready)
output
is_open
// i2c channel is open (started, no stop yet)
...
...
@@ -119,6 +123,14 @@ module sensor_i2c_scl_sda(
seq_start_restart
[
3
]
||
seq_start_restart
[
2
]
||
seq_stop
[
0
]
||
(
sr
[
8
]
&&
(
|
seq_bit
))
;
if
(
rst
)
sda_en
<=
1
;
else
if
(
first_cyc
)
sda_en
<=
busy_r
&&
(
(
active_sda
&&
(
seq_start_restart
[
3
]
||
seq_stop
[
0
]
||
(
sr
[
8
]
&&
seq_bit
[
3
])))
||
(
|
seq_start_restart
[
1
:
0
])
||
(
|
seq_stop
[
2
:
1
])
||
(
!
sr
[
8
]
&&
(
|
seq_bit
[
3
:
1
]))
||
(
!
sr
[
8
]
&&
seq_bit
[
0
]
&&
(
!
early_release_0
||
!
sr
[
7
])))
;
bus_busy
<=
busy_r
;
end
...
...
sensor/sensors393.v
View file @
74db68c1
...
...
@@ -54,17 +54,15 @@ module sensors393 #(
// sensor_i2c_io relative control register addresses
parameter
SENSI2C_CTRL
=
'h0
,
// Control register bits
parameter
SENSI2C_CMD_TABLE
=
29
,
// [29]: 1 - write to translation table (ignore any other fields), 0 - write other fields
parameter
SENSI2C_CMD_TAND
=
28
,
// [28]: 1 - write table address (8 bits), 0 - write table data (28 bits)
parameter
SENSI2C_CMD_RESET
=
14
,
// [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
parameter
SENSI2C_CMD_RUN
=
13
,
// [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
parameter
SENSI2C_CMD_RUN_PBITS
=
1
,
parameter
SENSI2C_CMD_BYTES
=
11
,
// if 1, use [10:9] to set command bytes to send after slave address (0..3)
parameter
SENSI2C_CMD_BYTES_PBITS
=
2
,
parameter
SENSI2C_CMD_DLY
=
8
,
// [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
parameter
SENSI2C_CMD_DLY_PBITS
=
8
,
parameter
SENSI2C_CMD_SCL
=
16
,
// [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
parameter
SENSI2C_CMD_SCL_WIDTH
=
2
,
parameter
SENSI2C_CMD_SDA
=
18
,
// [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA,
parameter
SENSI2C_CMD_SDA_WIDTH
=
2
,
parameter
SENSI2C_CMD_FIFO_RD
=
3
,
// advane I2C read data FIFO by 1
parameter
SENSI2C_CMD_ACIVE
=
2
,
// [2] - SENSI2C_CMD_ACIVE_EARLY0, SENSI2C_CMD_ACIVE_SDA
parameter
SENSI2C_CMD_ACIVE_EARLY0
=
1
,
// release SDA==0 early if next bit ==1
parameter
SENSI2C_CMD_ACIVE_SDA
=
0
,
// drive SDA=1 during the second half of SCL=1
parameter
SENSI2C_STATUS
=
'h1
,
...
...
@@ -379,17 +377,15 @@ module sensors393 #(
.
SENSI2C_CTRL_RADDR
(
SENSI2C_CTRL_RADDR
)
,
.
SENSI2C_CTRL_MASK
(
SENSI2C_CTRL_MASK
)
,
.
SENSI2C_CTRL
(
SENSI2C_CTRL
)
,
.
SENSI2C_CMD_TABLE
(
SENSI2C_CMD_TABLE
)
,
.
SENSI2C_CMD_TAND
(
SENSI2C_CMD_TAND
)
,
.
SENSI2C_CMD_RESET
(
SENSI2C_CMD_RESET
)
,
.
SENSI2C_CMD_RUN
(
SENSI2C_CMD_RUN
)
,
.
SENSI2C_CMD_RUN_PBITS
(
SENSI2C_CMD_RUN_PBITS
)
,
.
SENSI2C_CMD_BYTES
(
SENSI2C_CMD_BYTES
)
,
.
SENSI2C_CMD_BYTES_PBITS
(
SENSI2C_CMD_BYTES_PBITS
)
,
.
SENSI2C_CMD_DLY
(
SENSI2C_CMD_DLY
)
,
.
SENSI2C_CMD_DLY_PBITS
(
SENSI2C_CMD_DLY_PBITS
)
,
.
SENSI2C_CMD_SCL
(
SENSI2C_CMD_SCL
)
,
.
SENSI2C_CMD_SCL_WIDTH
(
SENSI2C_CMD_SCL_WIDTH
)
,
.
SENSI2C_CMD_SDA
(
SENSI2C_CMD_SDA
)
,
.
SENSI2C_CMD_SDA_WIDTH
(
SENSI2C_CMD_SDA_WIDTH
)
,
.
SENSI2C_CMD_FIFO_RD
(
SENSI2C_CMD_FIFO_RD
)
,
.
SENSI2C_CMD_ACIVE
(
SENSI2C_CMD_ACIVE
)
,
.
SENSI2C_CMD_ACIVE_EARLY0
(
SENSI2C_CMD_ACIVE_EARLY0
)
,
.
SENSI2C_CMD_ACIVE_SDA
(
SENSI2C_CMD_ACIVE_SDA
)
,
.
SENSI2C_STATUS
(
SENSI2C_STATUS
)
,
.
SENS_GAMMA_RADDR
(
SENS_GAMMA_RADDR
)
,
.
SENS_GAMMA_ADDR_MASK
(
SENS_GAMMA_ADDR_MASK
)
,
...
...
x393.v
View file @
74db68c1
...
...
@@ -1422,17 +1422,15 @@ assign axi_grst = axi_rst_pre;
.
SENSI2C_CTRL_RADDR
(
SENSI2C_CTRL_RADDR
)
,
.
SENSI2C_CTRL_MASK
(
SENSI2C_CTRL_MASK
)
,
.
SENSI2C_CTRL
(
SENSI2C_CTRL
)
,
.
SENSI2C_CMD_TABLE
(
SENSI2C_CMD_TABLE
)
,
.
SENSI2C_CMD_TAND
(
SENSI2C_CMD_TAND
)
,
.
SENSI2C_CMD_RESET
(
SENSI2C_CMD_RESET
)
,
.
SENSI2C_CMD_RUN
(
SENSI2C_CMD_RUN
)
,
.
SENSI2C_CMD_RUN_PBITS
(
SENSI2C_CMD_RUN_PBITS
)
,
.
SENSI2C_CMD_BYTES
(
SENSI2C_CMD_BYTES
)
,
.
SENSI2C_CMD_BYTES_PBITS
(
SENSI2C_CMD_BYTES_PBITS
)
,
.
SENSI2C_CMD_DLY
(
SENSI2C_CMD_DLY
)
,
.
SENSI2C_CMD_DLY_PBITS
(
SENSI2C_CMD_DLY_PBITS
)
,
.
SENSI2C_CMD_SCL
(
SENSI2C_CMD_SCL
)
,
.
SENSI2C_CMD_SCL_WIDTH
(
SENSI2C_CMD_SCL_WIDTH
)
,
.
SENSI2C_CMD_SDA
(
SENSI2C_CMD_SDA
)
,
.
SENSI2C_CMD_SDA_WIDTH
(
SENSI2C_CMD_SDA_WIDTH
)
,
.
SENSI2C_CMD_FIFO_RD
(
SENSI2C_CMD_FIFO_RD
)
,
.
SENSI2C_CMD_ACIVE
(
SENSI2C_CMD_ACIVE
)
,
.
SENSI2C_CMD_ACIVE_EARLY0
(
SENSI2C_CMD_ACIVE_EARLY0
)
,
.
SENSI2C_CMD_ACIVE_SDA
(
SENSI2C_CMD_ACIVE_SDA
)
,
.
SENSI2C_STATUS
(
SENSI2C_STATUS
)
,
.
SENS_SYNC_RADDR
(
SENS_SYNC_RADDR
)
,
.
SENS_SYNC_MASK
(
SENS_SYNC_MASK
)
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment