mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 12:38:44 -07:00
cndm: Use state machine in queue state module to improve timing performance
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -191,7 +191,8 @@ assign m_axis_event.tid = '0;
|
|||||||
assign m_axis_event.tdest = m_axis_event_tdest_reg;
|
assign m_axis_event.tdest = m_axis_event_tdest_reg;
|
||||||
assign m_axis_event.tuser = '0;
|
assign m_axis_event.tuser = '0;
|
||||||
|
|
||||||
logic [2**QN_W-1:0] queue_enable_reg = '0;
|
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||||
|
logic queue_mem_enable[2**QN_W] = '{default: '0};
|
||||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||||
logic queue_mem_arm[2**QN_W] = '{default: '0};
|
logic queue_mem_arm[2**QN_W] = '{default: '0};
|
||||||
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
|
||||||
@@ -212,18 +213,18 @@ logic [PTR_W-1:0] queue_mem_prod_ptr[2**QN_W] = '{default: '0};
|
|||||||
logic [PTR_W-1:0] queue_mem_cons_ptr[2**QN_W] = '{default: '0};
|
logic [PTR_W-1:0] queue_mem_cons_ptr[2**QN_W] = '{default: '0};
|
||||||
|
|
||||||
logic queue_mem_wr_en;
|
logic queue_mem_wr_en;
|
||||||
logic [QN_W-1:0] queue_mem_addr;
|
logic [QN_W-1:0] queue_mem_addr_reg = '0, queue_mem_addr_next;
|
||||||
|
|
||||||
wire queue_mem_rd_enable = queue_enable_reg[queue_mem_addr];
|
wire queue_mem_rd_enable = queue_mem_enable[queue_mem_addr_reg];
|
||||||
wire queue_mem_rd_arm = queue_mem_arm[queue_mem_addr];
|
wire queue_mem_rd_arm = queue_mem_arm[queue_mem_addr_reg];
|
||||||
wire queue_mem_rd_fire = queue_mem_fire[queue_mem_addr];
|
wire queue_mem_rd_fire = queue_mem_fire[queue_mem_addr_reg];
|
||||||
wire queue_mem_rd_cq_irq = queue_mem_cq_irq[queue_mem_addr];
|
wire queue_mem_rd_cq_irq = queue_mem_cq_irq[queue_mem_addr_reg];
|
||||||
wire [2:0] queue_mem_rd_qtype = queue_mem_qtype[queue_mem_addr];
|
wire [2:0] queue_mem_rd_qtype = queue_mem_qtype[queue_mem_addr_reg];
|
||||||
wire [DQN_W-1:0] queue_mem_rd_dqn = queue_mem_dqn[queue_mem_addr];
|
wire [DQN_W-1:0] queue_mem_rd_dqn = queue_mem_dqn[queue_mem_addr_reg];
|
||||||
wire [3:0] queue_mem_rd_log_size = queue_mem_log_size[queue_mem_addr];
|
wire [3:0] queue_mem_rd_log_size = queue_mem_log_size[queue_mem_addr_reg];
|
||||||
wire [DMA_ADDR_W-1:0] queue_mem_rd_base_addr = queue_mem_base_addr[queue_mem_addr];
|
wire [DMA_ADDR_W-1:0] queue_mem_rd_base_addr = queue_mem_base_addr[queue_mem_addr_reg];
|
||||||
wire [PTR_W-1:0] queue_mem_rd_prod_ptr = queue_mem_prod_ptr[queue_mem_addr];
|
wire [PTR_W-1:0] queue_mem_rd_prod_ptr = queue_mem_prod_ptr[queue_mem_addr_reg];
|
||||||
wire [PTR_W-1:0] queue_mem_rd_cons_ptr = queue_mem_cons_ptr[queue_mem_addr];
|
wire [PTR_W-1:0] queue_mem_rd_cons_ptr = queue_mem_cons_ptr[queue_mem_addr_reg];
|
||||||
|
|
||||||
wire queue_mem_rd_status_empty = queue_mem_rd_prod_ptr == queue_mem_rd_cons_ptr;
|
wire queue_mem_rd_status_empty = queue_mem_rd_prod_ptr == queue_mem_rd_cons_ptr;
|
||||||
wire queue_mem_rd_status_full = ($unsigned(queue_mem_rd_prod_ptr - queue_mem_rd_cons_ptr) & ({PTR_W{1'b1}} << queue_mem_rd_log_size)) != 0;
|
wire queue_mem_rd_status_full = ($unsigned(queue_mem_rd_prod_ptr - queue_mem_rd_cons_ptr) & ({PTR_W{1'b1}} << queue_mem_rd_log_size)) != 0;
|
||||||
@@ -241,7 +242,21 @@ logic [PTR_W-1:0] queue_mem_wr_cons_ptr;
|
|||||||
|
|
||||||
logic [QN_W-1:0] scrub_ptr_reg = '0, scrub_ptr_next;
|
logic [QN_W-1:0] scrub_ptr_reg = '0, scrub_ptr_next;
|
||||||
|
|
||||||
|
typedef enum logic [2:0] {
|
||||||
|
STATE_INIT,
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_AXIL_WR,
|
||||||
|
STATE_APB,
|
||||||
|
STATE_NOTIFY,
|
||||||
|
STATE_REQ,
|
||||||
|
STATE_SCRUB
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
state_t state_reg = STATE_INIT, state_next;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
state_next = STATE_INIT;
|
||||||
|
|
||||||
s_axil_ctrl_awready_next = 1'b0;
|
s_axil_ctrl_awready_next = 1'b0;
|
||||||
s_axil_ctrl_wready_next = 1'b0;
|
s_axil_ctrl_wready_next = 1'b0;
|
||||||
s_axil_ctrl_bvalid_next = 1'b0;
|
s_axil_ctrl_bvalid_next = 1'b0;
|
||||||
@@ -271,7 +286,7 @@ always_comb begin
|
|||||||
m_axis_event_tvalid_next = m_axis_event_tvalid_reg && !m_axis_event.tready;
|
m_axis_event_tvalid_next = m_axis_event_tvalid_reg && !m_axis_event.tready;
|
||||||
|
|
||||||
queue_mem_wr_en = 1'b0;
|
queue_mem_wr_en = 1'b0;
|
||||||
queue_mem_addr = '0;
|
queue_mem_addr_next = queue_mem_addr_reg;
|
||||||
|
|
||||||
queue_mem_wr_enable = queue_mem_rd_enable;
|
queue_mem_wr_enable = queue_mem_rd_enable;
|
||||||
queue_mem_wr_arm = queue_mem_rd_arm;
|
queue_mem_wr_arm = queue_mem_rd_arm;
|
||||||
@@ -294,14 +309,78 @@ always_comb begin
|
|||||||
s_axil_ctrl_rvalid_next = 1'b1;
|
s_axil_ctrl_rvalid_next = 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
case (state_reg)
|
||||||
|
STATE_INIT: begin
|
||||||
|
// initialize queue RAM
|
||||||
|
|
||||||
|
queue_mem_wr_en = 1'b1;
|
||||||
|
|
||||||
|
queue_mem_wr_enable = 1'b0;
|
||||||
|
queue_mem_wr_arm = 1'b0;
|
||||||
|
queue_mem_wr_fire = 1'b0;
|
||||||
|
queue_mem_wr_cq_irq = 1'b0;
|
||||||
|
queue_mem_wr_qtype = '0;
|
||||||
|
queue_mem_wr_dqn = '0;
|
||||||
|
queue_mem_wr_log_size = '0;
|
||||||
|
queue_mem_wr_base_addr = '0;
|
||||||
|
queue_mem_wr_prod_ptr = '0;
|
||||||
|
queue_mem_wr_cons_ptr = '0;
|
||||||
|
|
||||||
|
queue_mem_addr_next = queue_mem_addr_reg + 1;
|
||||||
|
|
||||||
|
if (&queue_mem_addr_reg) begin
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_INIT;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_IDLE: begin
|
||||||
|
// Start new operation
|
||||||
|
|
||||||
if (s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin
|
if (s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin
|
||||||
// AXI lite write
|
// AXIL write
|
||||||
|
|
||||||
|
queue_mem_addr_next = s_axil_ctrl_awaddr_queue_index;
|
||||||
|
// s_axil_ctrl_awaddr_reg_index
|
||||||
|
|
||||||
|
state_next = STATE_AXIL_WR;
|
||||||
|
end else if (s_apb_dp_ctrl.penable && s_apb_dp_ctrl.psel && !s_apb_dp_ctrl_pready_reg) begin
|
||||||
|
// APB read/write
|
||||||
|
|
||||||
|
queue_mem_addr_next = s_apb_dp_ctrl_paddr_queue_index;
|
||||||
|
// s_apb_dp_ctrl.pwrite
|
||||||
|
// s_apb_dp_ctrl_paddr_reg_index
|
||||||
|
|
||||||
|
state_next = STATE_APB;
|
||||||
|
end else if (notify_req_valid && !notify_req_ready) begin
|
||||||
|
// Notify request
|
||||||
|
notify_req_ready_next = 1'b1;
|
||||||
|
|
||||||
|
queue_mem_addr_next = notify_req_qn;
|
||||||
|
|
||||||
|
state_next = STATE_NOTIFY;
|
||||||
|
end else if (req_valid && !req_ready && (!rsp_valid || rsp_ready)) begin
|
||||||
|
// Queue op request
|
||||||
|
|
||||||
|
queue_mem_addr_next = req_qn;
|
||||||
|
// req_qtype
|
||||||
|
|
||||||
|
state_next = STATE_REQ;
|
||||||
|
end else begin
|
||||||
|
// Scrub
|
||||||
|
|
||||||
|
queue_mem_addr_next = scrub_ptr_reg;
|
||||||
|
|
||||||
|
state_next = STATE_SCRUB;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_AXIL_WR: begin
|
||||||
|
// AXIL write
|
||||||
s_axil_ctrl_awready_next = 1'b1;
|
s_axil_ctrl_awready_next = 1'b1;
|
||||||
s_axil_ctrl_wready_next = 1'b1;
|
s_axil_ctrl_wready_next = 1'b1;
|
||||||
s_axil_ctrl_bvalid_next = 1'b1;
|
s_axil_ctrl_bvalid_next = 1'b1;
|
||||||
|
|
||||||
queue_mem_wr_en = 1'b1;
|
queue_mem_wr_en = 1'b1;
|
||||||
queue_mem_addr = s_axil_ctrl_awaddr_queue_index;
|
|
||||||
|
|
||||||
case (s_axil_ctrl_awaddr_reg_index)
|
case (s_axil_ctrl_awaddr_reg_index)
|
||||||
3'd2: begin
|
3'd2: begin
|
||||||
@@ -320,13 +399,14 @@ always_comb begin
|
|||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
end else if (s_apb_dp_ctrl.penable && s_apb_dp_ctrl.psel && !s_apb_dp_ctrl_pready_reg) begin
|
// go to scrub state to attempt generating event/IRQ immediately
|
||||||
|
state_next = STATE_SCRUB;
|
||||||
|
end
|
||||||
|
STATE_APB: begin
|
||||||
// APB read/write
|
// APB read/write
|
||||||
s_apb_dp_ctrl_pready_next = 1'b1;
|
s_apb_dp_ctrl_pready_next = 1'b1;
|
||||||
s_apb_dp_ctrl_prdata_next = '0;
|
s_apb_dp_ctrl_prdata_next = '0;
|
||||||
|
|
||||||
queue_mem_addr = s_apb_dp_ctrl_paddr_queue_index;
|
|
||||||
|
|
||||||
if (s_apb_dp_ctrl.pwrite) begin
|
if (s_apb_dp_ctrl.pwrite) begin
|
||||||
queue_mem_wr_en = 1'b1;
|
queue_mem_wr_en = 1'b1;
|
||||||
|
|
||||||
@@ -375,21 +455,22 @@ always_comb begin
|
|||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
end else if (notify_req_valid && !notify_req_ready) begin
|
state_next = STATE_IDLE;
|
||||||
// notify request
|
end
|
||||||
notify_req_ready_next = 1'b1;
|
STATE_NOTIFY: begin
|
||||||
|
// Notify request
|
||||||
|
|
||||||
queue_mem_addr = notify_req_qn;
|
|
||||||
queue_mem_wr_fire = 1'b1;
|
queue_mem_wr_fire = 1'b1;
|
||||||
|
|
||||||
queue_mem_wr_en = 1'b1;
|
queue_mem_wr_en = 1'b1;
|
||||||
end else if (req_valid && !req_ready && (!rsp_valid || rsp_ready)) begin
|
|
||||||
// completion enqueue request
|
// go to scrub state to attempt generating event/IRQ immediately
|
||||||
|
state_next = STATE_SCRUB;
|
||||||
|
end
|
||||||
|
STATE_REQ: begin
|
||||||
|
// Queue op request
|
||||||
req_ready_next = 1'b1;
|
req_ready_next = 1'b1;
|
||||||
|
|
||||||
queue_mem_addr = req_qn;
|
rsp_qn_next = queue_mem_addr_reg;
|
||||||
|
|
||||||
rsp_qn_next = req_qn;
|
|
||||||
rsp_dqn_next = queue_mem_rd_dqn;
|
rsp_dqn_next = queue_mem_rd_dqn;
|
||||||
rsp_error_next = !queue_mem_rd_enable || (QTYPE_EN && req_qtype != queue_mem_rd_qtype);
|
rsp_error_next = !queue_mem_rd_enable || (QTYPE_EN && req_qtype != queue_mem_rd_qtype);
|
||||||
if (IS_CQ || IS_EQ) begin
|
if (IS_CQ || IS_EQ) begin
|
||||||
@@ -409,10 +490,11 @@ always_comb begin
|
|||||||
if (!rsp_error_next) begin
|
if (!rsp_error_next) begin
|
||||||
queue_mem_wr_en = 1'b1;
|
queue_mem_wr_en = 1'b1;
|
||||||
end
|
end
|
||||||
end else begin
|
|
||||||
// scrub
|
|
||||||
|
|
||||||
queue_mem_addr = scrub_ptr_reg;
|
state_next = STATE_IDLE;
|
||||||
|
end
|
||||||
|
STATE_SCRUB: begin
|
||||||
|
// Scrub
|
||||||
|
|
||||||
if ((IS_CQ || IS_EQ) && queue_mem_rd_enable && queue_mem_rd_arm && queue_mem_rd_fire) begin
|
if ((IS_CQ || IS_EQ) && queue_mem_rd_enable && queue_mem_rd_arm && queue_mem_rd_fire) begin
|
||||||
if ((IS_CQ && !IS_EQ && (!CQ_IRQ || !queue_mem_rd_cq_irq)) || (QTYPE_EN && queue_mem_rd_qtype == QTYPE_CQ && (!CQ_IRQ || !queue_mem_rd_cq_irq))) begin
|
if ((IS_CQ && !IS_EQ && (!CQ_IRQ || !queue_mem_rd_cq_irq)) || (QTYPE_EN && queue_mem_rd_qtype == QTYPE_CQ && (!CQ_IRQ || !queue_mem_rd_cq_irq))) begin
|
||||||
@@ -423,7 +505,7 @@ always_comb begin
|
|||||||
m_axis_event_tdata_next = '0;
|
m_axis_event_tdata_next = '0;
|
||||||
m_axis_event_tdata_next[15:0] = '0; // rsvd
|
m_axis_event_tdata_next[15:0] = '0; // rsvd
|
||||||
m_axis_event_tdata_next[31:16] = '0; // CPL
|
m_axis_event_tdata_next[31:16] = '0; // CPL
|
||||||
m_axis_event_tdata_next[63:32] = 32'(scrub_ptr_reg); // CQN
|
m_axis_event_tdata_next[63:32] = 32'(queue_mem_addr_reg); // CQN
|
||||||
m_axis_event_tdest_next = EQN_W'(queue_mem_rd_dqn);
|
m_axis_event_tdest_next = EQN_W'(queue_mem_rd_dqn);
|
||||||
m_axis_event_tvalid_next = 1'b1;
|
m_axis_event_tvalid_next = 1'b1;
|
||||||
|
|
||||||
@@ -446,11 +528,22 @@ always_comb begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (scrub_ptr_reg == queue_mem_addr_reg) begin
|
||||||
scrub_ptr_next = scrub_ptr_reg + 1;
|
scrub_ptr_next = scrub_ptr_reg + 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
// invalid state
|
||||||
|
state_next = STATE_INIT;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
|
state_reg <= state_next;
|
||||||
|
|
||||||
s_axil_ctrl_awready_reg <= s_axil_ctrl_awready_next;
|
s_axil_ctrl_awready_reg <= s_axil_ctrl_awready_next;
|
||||||
s_axil_ctrl_wready_reg <= s_axil_ctrl_wready_next;
|
s_axil_ctrl_wready_reg <= s_axil_ctrl_wready_next;
|
||||||
s_axil_ctrl_bvalid_reg <= s_axil_ctrl_bvalid_next;
|
s_axil_ctrl_bvalid_reg <= s_axil_ctrl_bvalid_next;
|
||||||
@@ -481,20 +574,23 @@ always @(posedge clk) begin
|
|||||||
|
|
||||||
scrub_ptr_reg <= scrub_ptr_next;
|
scrub_ptr_reg <= scrub_ptr_next;
|
||||||
|
|
||||||
|
queue_mem_addr_reg <= queue_mem_addr_next;
|
||||||
if (queue_mem_wr_en) begin
|
if (queue_mem_wr_en) begin
|
||||||
queue_enable_reg[queue_mem_addr] <= queue_mem_wr_enable;
|
queue_mem_enable[queue_mem_addr_reg] <= queue_mem_wr_enable;
|
||||||
queue_mem_arm[queue_mem_addr] <= queue_mem_wr_arm;
|
queue_mem_arm[queue_mem_addr_reg] <= queue_mem_wr_arm;
|
||||||
queue_mem_fire[queue_mem_addr] <= queue_mem_wr_fire;
|
queue_mem_fire[queue_mem_addr_reg] <= queue_mem_wr_fire;
|
||||||
queue_mem_cq_irq[queue_mem_addr] <= queue_mem_wr_cq_irq;
|
queue_mem_cq_irq[queue_mem_addr_reg] <= queue_mem_wr_cq_irq;
|
||||||
queue_mem_qtype[queue_mem_addr] <= queue_mem_wr_qtype;
|
queue_mem_qtype[queue_mem_addr_reg] <= queue_mem_wr_qtype;
|
||||||
queue_mem_dqn[queue_mem_addr] <= queue_mem_wr_dqn;
|
queue_mem_dqn[queue_mem_addr_reg] <= queue_mem_wr_dqn;
|
||||||
queue_mem_log_size[queue_mem_addr] <= queue_mem_wr_log_size;
|
queue_mem_log_size[queue_mem_addr_reg] <= queue_mem_wr_log_size;
|
||||||
queue_mem_base_addr[queue_mem_addr] <= queue_mem_wr_base_addr;
|
queue_mem_base_addr[queue_mem_addr_reg] <= queue_mem_wr_base_addr;
|
||||||
queue_mem_prod_ptr[queue_mem_addr] <= queue_mem_wr_prod_ptr;
|
queue_mem_prod_ptr[queue_mem_addr_reg] <= queue_mem_wr_prod_ptr;
|
||||||
queue_mem_cons_ptr[queue_mem_addr] <= queue_mem_wr_cons_ptr;
|
queue_mem_cons_ptr[queue_mem_addr_reg] <= queue_mem_wr_cons_ptr;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
|
state_reg <= STATE_INIT;
|
||||||
|
|
||||||
s_axil_ctrl_awready_reg <= 1'b0;
|
s_axil_ctrl_awready_reg <= 1'b0;
|
||||||
s_axil_ctrl_wready_reg <= 1'b0;
|
s_axil_ctrl_wready_reg <= 1'b0;
|
||||||
s_axil_ctrl_bvalid_reg <= 1'b0;
|
s_axil_ctrl_bvalid_reg <= 1'b0;
|
||||||
@@ -515,7 +611,7 @@ always @(posedge clk) begin
|
|||||||
|
|
||||||
scrub_ptr_reg <= '0;
|
scrub_ptr_reg <= '0;
|
||||||
|
|
||||||
queue_enable_reg <= '0;
|
queue_mem_addr_reg <= '0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user