mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 12:38:44 -07:00
lss: Add tBUF setting to I2C master to insert bus idle time before starts and repeated starts
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -45,7 +45,8 @@ module taxi_i2c_master (
|
|||||||
/*
|
/*
|
||||||
* Configuration
|
* Configuration
|
||||||
*/
|
*/
|
||||||
input wire logic [15:0] prescale,
|
input wire logic [15:0] prescale = 10,
|
||||||
|
input wire logic [15:0] tbuf_cyc = 10,
|
||||||
input wire logic stop_on_idle
|
input wire logic stop_on_idle
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -118,6 +119,10 @@ prescale
|
|||||||
set prescale to 1/4 of the minimum clock period in units
|
set prescale to 1/4 of the minimum clock period in units
|
||||||
of input clk cycles (prescale = Fclk / (FI2Cclk * 4))
|
of input clk cycles (prescale = Fclk / (FI2Cclk * 4))
|
||||||
|
|
||||||
|
tbuf_cyc
|
||||||
|
bus free time (tBUF) before a start or repeated start in
|
||||||
|
units of bit periods / scl cycles
|
||||||
|
|
||||||
stop_on_idle
|
stop_on_idle
|
||||||
automatically issue stop when command input is not valid
|
automatically issue stop when command input is not valid
|
||||||
|
|
||||||
@@ -214,8 +219,10 @@ logic mode_read_reg = 1'b0, mode_read_next;
|
|||||||
logic mode_write_multiple_reg = 1'b0, mode_write_multiple_next;
|
logic mode_write_multiple_reg = 1'b0, mode_write_multiple_next;
|
||||||
logic mode_stop_reg = 1'b0, mode_stop_next;
|
logic mode_stop_reg = 1'b0, mode_stop_next;
|
||||||
|
|
||||||
logic [15:0] delay_count_reg = '0, delay_count_next;
|
logic [15:0] delay_count_qb_reg = '0, delay_count_qb_next;
|
||||||
|
logic [15+2:0] delay_count_tbuf_reg = '0, delay_count_tbuf_next;
|
||||||
logic delay_run_reg = 1'b0, delay_run_next;
|
logic delay_run_reg = 1'b0, delay_run_next;
|
||||||
|
logic delay_tbuf_reg = 1'b0, delay_tbuf_next;
|
||||||
logic delay_scl_reg = 1'b0, delay_scl_next;
|
logic delay_scl_reg = 1'b0, delay_scl_next;
|
||||||
logic delay_sda_reg = 1'b0, delay_sda_next;
|
logic delay_sda_reg = 1'b0, delay_sda_next;
|
||||||
|
|
||||||
@@ -595,8 +602,10 @@ always_comb begin
|
|||||||
phy_ready_next = 1'b0;
|
phy_ready_next = 1'b0;
|
||||||
phy_rx_data_next = phy_rx_data_reg;
|
phy_rx_data_next = phy_rx_data_reg;
|
||||||
|
|
||||||
delay_count_next = delay_count_reg;
|
delay_count_qb_next = delay_count_qb_reg;
|
||||||
|
delay_count_tbuf_next = delay_count_tbuf_reg;
|
||||||
delay_run_next = delay_run_reg;
|
delay_run_next = delay_run_reg;
|
||||||
|
delay_tbuf_next = delay_tbuf_reg;
|
||||||
delay_scl_next = delay_scl_reg;
|
delay_scl_next = delay_scl_reg;
|
||||||
delay_sda_next = delay_sda_reg;
|
delay_sda_next = delay_sda_reg;
|
||||||
|
|
||||||
@@ -613,13 +622,18 @@ always_comb begin
|
|||||||
delay_sda_next = sda_o_reg && !sda_i_reg;
|
delay_sda_next = sda_o_reg && !sda_i_reg;
|
||||||
end else if (delay_run_reg) begin
|
end else if (delay_run_reg) begin
|
||||||
// time delay
|
// time delay
|
||||||
if (delay_count_reg != 0) begin
|
if (delay_count_qb_reg != 0) begin
|
||||||
delay_count_next = delay_count_reg - 1;
|
delay_count_qb_next = delay_count_qb_reg - 1;
|
||||||
|
end else if (delay_tbuf_reg && delay_count_tbuf_reg != 0) begin
|
||||||
|
delay_count_qb_next = prescale;
|
||||||
|
delay_count_tbuf_next = delay_count_tbuf_reg - 1;
|
||||||
end else begin
|
end else begin
|
||||||
delay_run_next = 1'b0;
|
delay_run_next = 1'b0;
|
||||||
|
delay_tbuf_next = 1'b0;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
delay_count_next = prescale;
|
delay_count_qb_next = prescale;
|
||||||
|
delay_count_tbuf_next = {tbuf_cyc, 2'b00};
|
||||||
end
|
end
|
||||||
|
|
||||||
if (phy_release_bus) begin
|
if (phy_release_bus) begin
|
||||||
@@ -662,6 +676,7 @@ always_comb begin
|
|||||||
phy_ready_next = 1'b0;
|
phy_ready_next = 1'b0;
|
||||||
sda_o_next = 1'b1;
|
sda_o_next = 1'b1;
|
||||||
delay_run_next = 1'b1;
|
delay_run_next = 1'b1;
|
||||||
|
delay_tbuf_next = 1'b1;
|
||||||
phy_state_next = PHY_STATE_REPEATED_START_1;
|
phy_state_next = PHY_STATE_REPEATED_START_1;
|
||||||
end else if (phy_write_bit && phy_ready_reg) begin
|
end else if (phy_write_bit && phy_ready_reg) begin
|
||||||
phy_ready_next = 1'b0;
|
phy_ready_next = 1'b0;
|
||||||
@@ -818,6 +833,7 @@ always_comb begin
|
|||||||
|
|
||||||
sda_o_next = 1'b1;
|
sda_o_next = 1'b1;
|
||||||
delay_run_next = 1'b1;
|
delay_run_next = 1'b1;
|
||||||
|
delay_tbuf_next = 1'b1;
|
||||||
phy_state_next = PHY_STATE_STOP_3;
|
phy_state_next = PHY_STATE_STOP_3;
|
||||||
end
|
end
|
||||||
PHY_STATE_STOP_3: begin
|
PHY_STATE_STOP_3: begin
|
||||||
@@ -852,8 +868,10 @@ always_ff @(posedge clk) begin
|
|||||||
mode_write_multiple_reg <= mode_write_multiple_next;
|
mode_write_multiple_reg <= mode_write_multiple_next;
|
||||||
mode_stop_reg <= mode_stop_next;
|
mode_stop_reg <= mode_stop_next;
|
||||||
|
|
||||||
delay_count_reg <= delay_count_next;
|
delay_count_qb_reg <= delay_count_qb_next;
|
||||||
|
delay_count_tbuf_reg <= delay_count_tbuf_next;
|
||||||
delay_run_reg <= delay_run_next;
|
delay_run_reg <= delay_run_next;
|
||||||
|
delay_tbuf_reg <= delay_tbuf_next;
|
||||||
delay_scl_reg <= delay_scl_next;
|
delay_scl_reg <= delay_scl_next;
|
||||||
delay_sda_reg <= delay_sda_next;
|
delay_sda_reg <= delay_sda_next;
|
||||||
|
|
||||||
@@ -892,8 +910,10 @@ always_ff @(posedge clk) begin
|
|||||||
if (rst) begin
|
if (rst) begin
|
||||||
state_reg <= STATE_IDLE;
|
state_reg <= STATE_IDLE;
|
||||||
phy_state_reg <= PHY_STATE_IDLE;
|
phy_state_reg <= PHY_STATE_IDLE;
|
||||||
delay_count_reg <= '0;
|
delay_count_qb_reg <= '0;
|
||||||
|
delay_count_tbuf_reg <= '0;
|
||||||
delay_run_reg <= 1'b0;
|
delay_run_reg <= 1'b0;
|
||||||
|
delay_tbuf_reg <= 1'b0;
|
||||||
delay_scl_reg <= 1'b0;
|
delay_scl_reg <= 1'b0;
|
||||||
delay_sda_reg <= 1'b0;
|
delay_sda_reg <= 1'b0;
|
||||||
s_axis_cmd_ready_reg <= 1'b0;
|
s_axis_cmd_ready_reg <= 1'b0;
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ class TB:
|
|||||||
self.i2c_mem.append(I2cMemory(sda=dut.sda_o, sda_o=dut.sda_i,
|
self.i2c_mem.append(I2cMemory(sda=dut.sda_o, sda_o=dut.sda_i,
|
||||||
scl=dut.scl_o, scl_o=dut.scl_i, addr=0x51, size=1024))
|
scl=dut.scl_o, scl_o=dut.scl_i, addr=0x51, size=1024))
|
||||||
|
|
||||||
dut.prescale.setimmediatevalue(2)
|
dut.prescale.setimmediatevalue(20)
|
||||||
|
dut.tbuf_cyc.setimmediatevalue(20)
|
||||||
dut.stop_on_idle.setimmediatevalue(0)
|
dut.stop_on_idle.setimmediatevalue(0)
|
||||||
|
|
||||||
async def reset(self):
|
async def reset(self):
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ logic bus_active;
|
|||||||
logic missed_ack;
|
logic missed_ack;
|
||||||
|
|
||||||
logic [15:0] prescale;
|
logic [15:0] prescale;
|
||||||
|
logic [15:0] tbuf_cyc;
|
||||||
logic stop_on_idle;
|
logic stop_on_idle;
|
||||||
|
|
||||||
taxi_i2c_master
|
taxi_i2c_master
|
||||||
@@ -70,6 +71,7 @@ uut (
|
|||||||
* Configuration
|
* Configuration
|
||||||
*/
|
*/
|
||||||
.prescale(prescale),
|
.prescale(prescale),
|
||||||
|
.tbuf_cyc(tbuf_cyc),
|
||||||
.stop_on_idle(stop_on_idle)
|
.stop_on_idle(stop_on_idle)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user