cndm: Add page select delay to board control logic

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-03-18 13:25:19 -07:00
parent bc3d0f0825
commit cb2a7af632
3 changed files with 57 additions and 4 deletions

View File

@@ -414,8 +414,10 @@ localparam logic [DEV_CNT-1:0][6:0] DEV_I2C_ADDR = {7'h5D, 7'h54, 7'h50, 7'h50};
localparam logic [DEV_CNT-1:0][31:0] DEV_ADDR_CFG = {32'h00_00_0000, 32'h00_00_0040, 32'h7e_7f_0070, 32'h7e_7f_0070}; localparam logic [DEV_CNT-1:0][31:0] DEV_ADDR_CFG = {32'h00_00_0000, 32'h00_00_0040, 32'h7e_7f_0070, 32'h7e_7f_0070};
localparam logic [DEV_CNT-1:0][MUX_CNT-1:0][7:0] DEV_MUX_MASK = {{8'h00, 8'h01}, {8'h07, 8'h00}, {8'h00, 8'h08}, {8'h00, 8'h04}}; localparam logic [DEV_CNT-1:0][MUX_CNT-1:0][7:0] DEV_MUX_MASK = {{8'h00, 8'h01}, {8'h07, 8'h00}, {8'h00, 8'h08}, {8'h00, 8'h04}};
localparam CYC_PER_US = 250;
localparam PAGE_SEL_DELAY_US = SIM ? 20 : 2000;
localparam I2C_PRESCALE = SIM ? 2 : 250000/(400*4); localparam I2C_PRESCALE = SIM ? 2 : 250000/(400*4);
localparam I2C_TBUF_CYC = SIM ? 10 : 1000; localparam I2C_TBUF_CYC = 20;
taxi_axis_if #( taxi_axis_if #(
.DATA_W(32), .DATA_W(32),
@@ -456,6 +458,8 @@ cndm_brd_ctrl_i2c #(
.DEV_ADDR_CFG(DEV_ADDR_CFG), .DEV_ADDR_CFG(DEV_ADDR_CFG),
.DEV_MUX_MASK(DEV_MUX_MASK), .DEV_MUX_MASK(DEV_MUX_MASK),
.CYC_PER_US(CYC_PER_US),
.PAGE_SEL_DELAY_US(PAGE_SEL_DELAY_US),
.I2C_PRESCALE(I2C_PRESCALE), .I2C_PRESCALE(I2C_PRESCALE),
.I2C_TBUF_CYC(I2C_TBUF_CYC) .I2C_TBUF_CYC(I2C_TBUF_CYC)
) )

View File

@@ -372,8 +372,10 @@ localparam logic [DEV_CNT-1:0][6:0] DEV_I2C_ADDR = {7'h50};
localparam logic [DEV_CNT-1:0][31:0] DEV_ADDR_CFG = {32'h7e_7f_0070}; localparam logic [DEV_CNT-1:0][31:0] DEV_ADDR_CFG = {32'h7e_7f_0070};
localparam logic [DEV_CNT-1:0][MUX_CNT-1:0][7:0] DEV_MUX_MASK = '0; localparam logic [DEV_CNT-1:0][MUX_CNT-1:0][7:0] DEV_MUX_MASK = '0;
localparam CYC_PER_US = 250;
localparam PAGE_SEL_DELAY_US = SIM ? 20 : 2000;
localparam I2C_PRESCALE = SIM ? 2 : 250000/(400*4); localparam I2C_PRESCALE = SIM ? 2 : 250000/(400*4);
localparam I2C_TBUF_CYC = SIM ? 10 : 1000; localparam I2C_TBUF_CYC = 20;
taxi_axis_if #( taxi_axis_if #(
.DATA_W(32), .DATA_W(32),
@@ -414,6 +416,8 @@ cndm_brd_ctrl_i2c #(
.DEV_ADDR_CFG(DEV_ADDR_CFG), .DEV_ADDR_CFG(DEV_ADDR_CFG),
.DEV_MUX_MASK(DEV_MUX_MASK), .DEV_MUX_MASK(DEV_MUX_MASK),
.CYC_PER_US(CYC_PER_US),
.PAGE_SEL_DELAY_US(PAGE_SEL_DELAY_US),
.I2C_PRESCALE(I2C_PRESCALE), .I2C_PRESCALE(I2C_PRESCALE),
.I2C_TBUF_CYC(I2C_TBUF_CYC) .I2C_TBUF_CYC(I2C_TBUF_CYC)
) )

View File

@@ -73,6 +73,10 @@ module cndm_brd_ctrl_i2c #
// Mux settings for each device // Mux settings for each device
parameter logic [DEV_CNT-1:0][MUX_CNT-1:0][7:0] DEV_MUX_MASK = '0, parameter logic [DEV_CNT-1:0][MUX_CNT-1:0][7:0] DEV_MUX_MASK = '0,
// Clock cycles per microsecond
parameter CYC_PER_US = 125,
// Page select delay in microseconds
parameter PAGE_SEL_DELAY_US = 2000,
// Prescaler for I2C master // Prescaler for I2C master
parameter I2C_PRESCALE = 125000/(400*4), parameter I2C_PRESCALE = 125000/(400*4),
// tBUF in I2C clock cycles // tBUF in I2C clock cycles
@@ -106,6 +110,9 @@ localparam CMD_ID_W = s_axis_cmd.ID_W;
localparam CL_DEV_IDX = DEV_CNT > 1 ? $clog2(DEV_CNT) : 1; localparam CL_DEV_IDX = DEV_CNT > 1 ? $clog2(DEV_CNT) : 1;
localparam CL_MUX_IDX = MUX_CNT > 1 ? $clog2(MUX_CNT) : 1; localparam CL_MUX_IDX = MUX_CNT > 1 ? $clog2(MUX_CNT) : 1;
localparam CL_US_CNT = $clog2(CYC_PER_US+1);
localparam CL_PGSEL_DELAY = $clog2(PAGE_SEL_DELAY_US+1);
typedef enum logic [15:0] { typedef enum logic [15:0] {
CMD_BRD_OP_NOP = 16'h0000, CMD_BRD_OP_NOP = 16'h0000,
@@ -312,6 +319,22 @@ logic [31:0] dev_addr_cfg_reg = '0, dev_addr_cfg_next;
logic [1:0] addr_ptr_reg = '0, addr_ptr_next; logic [1:0] addr_ptr_reg = '0, addr_ptr_next;
logic mode_write_reg = 1'b0, mode_write_next; logic mode_write_reg = 1'b0, mode_write_next;
logic [CL_PGSEL_DELAY-1:0] pgsel_delay_cnt_reg = '0, pgsel_delay_cnt_next;
logic pgsel_delay_reg = 1'b0, pgsel_delay_next;
logic [CL_US_CNT-1:0] us_cnt_reg = '0;
logic us_pulse_reg = 1'b0;
always @(posedge clk) begin
us_pulse_reg <= 1'b0;
if (us_cnt_reg != 0) begin
us_cnt_reg <= us_cnt_reg - 1;
end else begin
us_cnt_reg <= CYC_PER_US;
us_pulse_reg <= 1'b1;
end
end
always_comb begin always_comb begin
state_next = STATE_IDLE; state_next = STATE_IDLE;
ret_state_next = ret_state_reg; ret_state_next = ret_state_reg;
@@ -369,6 +392,9 @@ always_comb begin
addr_ptr_next = addr_ptr_reg; addr_ptr_next = addr_ptr_reg;
mode_write_next = mode_write_reg; mode_write_next = mode_write_reg;
pgsel_delay_cnt_next = pgsel_delay_cnt_reg;
pgsel_delay_next = pgsel_delay_reg;
if (s_axis_cmd.tready && s_axis_cmd.tvalid) begin if (s_axis_cmd.tready && s_axis_cmd.tvalid) begin
if (s_axis_cmd.tlast) begin if (s_axis_cmd.tlast) begin
cmd_frame_next = 1'b0; cmd_frame_next = 1'b0;
@@ -379,6 +405,18 @@ always_comb begin
end end
end end
if (pgsel_delay_reg) begin
if (us_pulse_reg) begin
if (pgsel_delay_cnt_reg != 0) begin
pgsel_delay_cnt_next = pgsel_delay_cnt_reg - 1;
end else begin
pgsel_delay_next = 1'b0;
end
end
end else begin
pgsel_delay_cnt_next = PAGE_SEL_DELAY_US;
end
case (state_reg) case (state_reg)
STATE_IDLE: begin STATE_IDLE: begin
dev_sel_next = '0; dev_sel_next = '0;
@@ -694,6 +732,8 @@ always_comb begin
axis_i2c_tx_tlast_next = 1'b1; axis_i2c_tx_tlast_next = 1'b1;
axis_i2c_tx_tvalid_next = 1'b1; axis_i2c_tx_tvalid_next = 1'b1;
pgsel_delay_next = 1'b1;
if (dev_addr_cfg_next[4]) begin if (dev_addr_cfg_next[4]) begin
state_next = STATE_I2C_SET_PAGE_1; state_next = STATE_I2C_SET_PAGE_1;
end else begin end else begin
@@ -705,7 +745,7 @@ always_comb begin
end end
STATE_I2C_SET_PAGE_1: begin STATE_I2C_SET_PAGE_1: begin
// Select page register // Select page register
if (!axis_i2c_cmd_tvalid_reg && !axis_i2c_tx_tvalid_reg) begin if (!axis_i2c_cmd_tvalid_reg && !axis_i2c_tx_tvalid_reg && !pgsel_delay_reg) begin
axis_i2c_cmd_tdata_next = 12'(i2c_addr_reg) | I2C_CMD_START | I2C_CMD_WRITE; axis_i2c_cmd_tdata_next = 12'(i2c_addr_reg) | I2C_CMD_START | I2C_CMD_WRITE;
axis_i2c_cmd_tvalid_next = 1'b1; axis_i2c_cmd_tvalid_next = 1'b1;
@@ -728,6 +768,8 @@ always_comb begin
axis_i2c_tx_tlast_next = 1'b1; axis_i2c_tx_tlast_next = 1'b1;
axis_i2c_tx_tvalid_next = 1'b1; axis_i2c_tx_tvalid_next = 1'b1;
pgsel_delay_next = 1'b1;
state_next = STATE_I2C_SET_ADDR_1; state_next = STATE_I2C_SET_ADDR_1;
end else begin end else begin
state_next = STATE_I2C_SET_PAGE_2; state_next = STATE_I2C_SET_PAGE_2;
@@ -735,7 +777,7 @@ always_comb begin
end end
STATE_I2C_SET_ADDR_1: begin STATE_I2C_SET_ADDR_1: begin
// Set device internal address // Set device internal address
if (!axis_i2c_cmd_tvalid_reg && !axis_i2c_tx_tvalid_reg) begin if (!axis_i2c_cmd_tvalid_reg && !axis_i2c_tx_tvalid_reg && !pgsel_delay_reg) begin
axis_i2c_cmd_tdata_next = 12'(i2c_addr_reg) | I2C_CMD_START | I2C_CMD_WRITE; axis_i2c_cmd_tdata_next = 12'(i2c_addr_reg) | I2C_CMD_START | I2C_CMD_WRITE;
axis_i2c_cmd_tvalid_next = 1'b1; axis_i2c_cmd_tvalid_next = 1'b1;
@@ -965,6 +1007,9 @@ always_ff @(posedge clk) begin
addr_ptr_reg <= addr_ptr_next; addr_ptr_reg <= addr_ptr_next;
mode_write_reg <= mode_write_next; mode_write_reg <= mode_write_next;
pgsel_delay_cnt_reg <= pgsel_delay_cnt_next;
pgsel_delay_reg <= pgsel_delay_next;
if (rst) begin if (rst) begin
state_reg <= STATE_IDLE; state_reg <= STATE_IDLE;