module array_rd ( input clk, input rst_n, input array_rd_frame_valid, input [151:0] array_rd_frame_data, output array_rd_frame_ready, output array_rd_done, output reg array_rd_csn, output reg [15:0] array_rd_raddr, output reg array_caddr_vld_rd, output reg [5:0] array_caddr_rd, input array_rdata_vld, input [127:0] array_rdata, input [7:0] array_inner_tras, input [7:0] array_inner_trp, input [7:0] array_inner_trcd_rd, input [7:0] array_inner_trtp, output array2axi_rdata_valid, output [127:0] array2axi_rdata ); reg [2:0] cur_state,next_state; localparam [2:0] ARR_RD_IDLE = 3'b000; localparam [2:0] ARR_RD_LOWCS = 3'b001; localparam [2:0] ARR_RD_RCD = 3'b010; localparam [2:0] ARR_RD_HIGHVLD = 3'b011; localparam [2:0] ARR_RD_RADDRLAST = 3'b100; localparam [2:0] ARR_RD_RADDR = 3'b101; localparam [2:0] ARR_RD_RTP = 3'b110; localparam [2:0] ARR_RD_RP = 3'b111; wire rsof,reof; wire [15:0] rraddr; wire [5:0] rcaddr; wire [127:0] wdata; reg [7:0] rd_ras_cnt; reg [7:0] rd_rcd_cnt; reg [7:0] rd_rtp_cnt; reg [7:0] rd_rp_cnt; reg single_flag_rd; reg array_raddr_eof; wire async_fifo_r_wr_clk; wire async_fifo_r_wr_rst_n; wire async_fifo_r_wr_en; wire [127:0] async_fifo_r_wr_data; wire async_fifo_r_full; wire async_fifo_r_rd_clk; wire async_fifo_r_rd_rst_n; wire async_fifo_r_rd_en; wire [127:0] async_fifo_r_rd_data; wire async_fifo_r_empty; async_fifo #(.FIFO_DEPTH(4), .DATA_WIDTH(128) ) async_fifo_r ( .wr_clk (async_fifo_r_wr_clk), .wr_rst_n (async_fifo_r_wr_rst_n), .wr_en (async_fifo_r_wr_en), .wr_data (async_fifo_r_wr_data), .full (async_fifo_r_full), .rd_clk (async_fifo_r_rd_clk), .rd_rst_n (async_fifo_r_rd_rst_n), .rd_en (async_fifo_r_rd_en), .rd_data (async_fifo_r_rd_data), .empty (async_fifo_r_empty) ); assign {rsof,reof,rraddr,rcaddr,wdata} = array_rd_frame_data; assign array_rd_frame_ready = (cur_state == ARR_RD_IDLE || ((cur_state == ARR_RD_RADDR) && !array_caddr_vld_rd)); assign array_rd_done = (cur_state == ARR_RD_RP) && rd_rp_cnt == 'd0; assign array2axi_rdata_valid = !async_fifo_r_empty; assign array2axi_rdata = async_fifo_r_rd_data; assign async_fifo_r_wr_clk = array_rdata_vld; assign async_fifo_r_wr_rst_n = rst_n; assign async_fifo_r_wr_en = 1'b1; assign async_fifo_r_wr_data = array_rdata; assign async_fifo_r_rd_clk = clk; assign async_fifo_r_rd_rst_n = rst_n; assign async_fifo_r_rd_en = !async_fifo_r_empty; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cur_state <= ARR_RD_IDLE; end else begin cur_state <= next_state; end end always @(*) begin case (cur_state) ARR_RD_IDLE : begin if (array_rd_frame_valid && rsof) begin next_state = ARR_RD_LOWCS; end else begin next_state = ARR_RD_IDLE; end end ARR_RD_LOWCS : begin next_state = ARR_RD_RCD; end ARR_RD_RCD : begin if (rd_rcd_cnt == 'd0) begin next_state = ARR_RD_HIGHVLD; end else begin next_state = ARR_RD_RCD; end end ARR_RD_HIGHVLD : begin if (single_flag_rd) begin next_state = ARR_RD_RADDRLAST; end else begin next_state = ARR_RD_RADDR; end end ARR_RD_RADDRLAST : begin next_state = ARR_RD_RTP; end ARR_RD_RADDR : begin if (array_raddr_eof) begin next_state = ARR_RD_RTP; end else begin next_state = ARR_RD_RADDR; end end ARR_RD_RTP : begin if (rd_ras_cnt == 'd0 && rd_rtp_cnt == 'd0) begin next_state = ARR_RD_RP; end else begin next_state = ARR_RD_RTP; end end ARR_RD_RP : begin if (rd_rp_cnt == 'd0) begin next_state = ARR_RD_IDLE; end else begin next_state = ARR_RD_RP; end end default : begin next_state = ARR_RD_IDLE; end endcase end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_rd_csn <= 1'b1; end else if (cur_state == ARR_RD_LOWCS) begin array_rd_csn <= 1'b0; end else if (cur_state == ARR_RD_RTP && next_state == ARR_RD_RP) begin array_rd_csn <= 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_rd_raddr <= 'b0; end else if (array_rd_frame_valid && array_rd_frame_ready) begin array_rd_raddr <= rraddr; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_caddr_rd <= 'b0; end else if (array_rd_frame_valid && array_rd_frame_ready) begin array_caddr_rd <= rcaddr; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_caddr_vld_rd <= 'd0; end else if (array_caddr_vld_rd == 1'b1) begin array_caddr_vld_rd <= 1'b0; end else if (cur_state == ARR_RD_HIGHVLD || (cur_state == ARR_RD_RADDR && array_rd_frame_valid && array_rd_frame_ready)) begin array_caddr_vld_rd <= 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rd_ras_cnt <= 'd0; end else if (cur_state == ARR_RD_LOWCS) begin rd_ras_cnt <= array_inner_tras - 1'b1; end else if (rd_ras_cnt == 'd0) begin rd_ras_cnt <= rd_ras_cnt; end else begin rd_ras_cnt <= rd_ras_cnt - 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rd_rcd_cnt <= 'd0; end else if (cur_state == ARR_RD_LOWCS) begin rd_rcd_cnt <= array_inner_trcd_rd - 2'b10; end else if (cur_state == ARR_RD_RCD) begin if (rd_rcd_cnt == 'd0) begin rd_rcd_cnt <= rd_rcd_cnt; end else begin rd_rcd_cnt <= rd_rcd_cnt - 1'b1; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rd_rtp_cnt <= 'd0; end else if (cur_state == ARR_RD_LOWCS) begin rd_rtp_cnt <= array_inner_trtp - 1'b1; end else if (cur_state == ARR_RD_RTP) begin if (rd_rtp_cnt == 'd0) begin rd_rtp_cnt <= rd_rtp_cnt; end else begin rd_rtp_cnt <= rd_rtp_cnt - 1'b1; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rd_rp_cnt <= 'd0; end else if (cur_state == ARR_RD_LOWCS) begin rd_rp_cnt <= array_inner_trp - 1'b1; end else if (cur_state == ARR_RD_RP) begin if (rd_rp_cnt == 'd0) begin rd_rp_cnt <= rd_rp_cnt; end else begin rd_rp_cnt <= rd_rp_cnt - 1'b1; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin single_flag_rd <= 'd0; end else if (cur_state == ARR_RD_IDLE && array_rd_frame_valid && rsof) begin single_flag_rd <= reof; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_raddr_eof <= 'd0; end else if (array_rd_frame_valid && array_rd_frame_ready) begin array_raddr_eof <= reof; end else begin array_raddr_eof <= 'd0; end end endmodule