fsm
// fsm states
// 000 001 010 011 100 101
typedef enum logic [2:0] {IDLE, AWVALID, WRDY, INCR_ENTRY, INCR_Q, CHK_VLD_Q} states_t;
states_t curr_st, next_st;
//==========================================================================
// wires and registers declarations
//==========================================================================
logic [14:0] entry_num;
logic [5:0] queue_num;
logic [15:0] queue_num_wrdata;
logic [15:0] entry_num_wrdata;
/***************************************************************************
*
*
* AXI write generates one entry by one entry to CQ with correct data
*
*
**************************************************************************/
assign s_axi_ssd_awid = 'h0;
assign s_axi_ssd_awlen = 'h0;
assign s_axi_ssd_awburst = 2'b01;
assign s_axi_ssd_awsize = 3'b100; //128bits
assign s_axi_ssd_awcache = 4'h0;
assign s_axi_ssd_awprot = 3'b000;
assign s_axi_ssd_wstrb = '1;
assign s_axi_ssd_wlast = 1'b1; // as there's only 1 beat per write
assign s_axi_ssd_bready = 1'b1;
assign queue_num_wrdata = queue_num + 1'b1;
assign entry_num_wrdata = entry_num + 1'b1;
//
always_ff @ (posedge clk_core)
begin //{
if (!rst_n_core)
begin //{
curr_st <= IDLE;
end //}
else
begin //{
curr_st <= next_st;
end //}
end //}
always_comb
begin //{
case (curr_st) //{
IDLE:
begin //{
next_st = current_ssd_sq_chk_done ? AWVALID : curr_st;
end //}
AWVALID:
begin //{
next_st = s_axi_ssd_awready ? WRDY : curr_st;
end //}
WRDY:
begin //{
if (s_axi_ssd_wready)
begin //{
// if last entry for that queue has been written:
if (sq_rxed[ssd_count_in][queue_num] - 1'b1 == entry_num)
begin //{
// if CQs for all queues are done writing go back to IDLE
if (queue_num == NUM_SQS - 1)
begin //{
next_st = IDLE;
end //}
// if not all CQs are written increment queue number
else
begin //{
next_st = INCR_Q;
end //}
end //}
// if all CQs for that queue are not written yet, write further
// CQs
else
begin //{
next_st = INCR_ENTRY;
end //}
end //}
else
begin //{
next_st = curr_st;
end //}
end //}
// increment entry number and generate AWVALID
INCR_ENTRY:
begin //{
next_st = AWVALID;
end //}
// increment Q and check for its validity
INCR_Q:
begin //{
next_st = CHK_VLD_Q;
end //}
default: // CHK_VLD_Q
begin //{
// if the incremented queue doesn't have any valid data
if (sq_rxed[ssd_count_in][queue_num] == 'h0)
begin //{
// and if this is the last queue go back to IDLE
if (queue_num == NUM_SQS - 1)
begin //{
next_st = IDLE;
end //}
// or else increment the queue to check for validity
// of next queue
else
begin //{
next_st = INCR_Q;
end //}
end //}
// if the incremented queue has valid data, go back to AWVALID
else
begin //{
next_st = AWVALID;
end //}
end //}
endcase //}
end //}
// when all CQs are written fsm goes to IDLE and that's when CQ write done is set
assign cq_write_done = (curr_st != IDLE) & (next_st == IDLE);
// AWValid generation
always_ff @ (posedge clk_core)
begin //{
if (!rst_n_core)
begin //{
s_axi_ssd_awvalid <= 1'b0;
s_axi_ssd_awaddr <= 'h0;
end //}
else if (next_st == AWVALID)
begin //{
s_axi_ssd_awvalid <= 1'b1;
s_axi_ssd_awaddr <= CQ_ADDR_ARRAY[ssd_count_in][queue_num] + (entry_num << 4);
end //}
else
begin //{
s_axi_ssd_awvalid <= 1'b0;
end //}
end //}
// wvalid and wdata
always_ff @ (posedge clk_core)
begin //{
if (!rst_n_core)
begin //{
s_axi_ssd_wvalid <= 1'b0;
s_axi_ssd_wdata <= 'h0;
end //}
else if (next_st == WRDY)
begin //{
s_axi_ssd_wvalid <= 1'b1;
// p sq header pointer
s_axi_ssd_wdata <= {15'd0,1'b1,8'd0,entry_num,10'd0, queue_num_wrdata, entry_num_wrdata,64'd0};
end //}
else
begin //{
s_axi_ssd_wvalid <= 1'b0;
end //}
end //}
// entry number increment
always_ff @ (posedge clk_core)
begin //{
if (!rst_n_core)
begin //{
entry_num <= 'h0;
end //}
else if (next_st == INCR_ENTRY)
begin //{
entry_num <= entry_num + 1'b1;
end //}
else if ((next_st == INCR_Q) | ((curr_st == WRDY) & (next_st == IDLE)))
begin //{
entry_num <= 'h0;
end //}
end //}
always_ff @ (posedge clk_core)
begin //{
if (!rst_n_core)
begin //{
queue_num <= 'h0;
end //}
else if (next_st == INCR_Q)
begin //{
queue_num <= queue_num + 1'b1;
end //}
else if (next_st == IDLE)
begin //{
queue_num <= 'h0;
end //}
end //}