module array_wr ( input clk, input rst_n, input array_wr_frame_valid, input [151:0] array_wr_frame_data, output array_wr_frame_ready, output array_wr_done, output reg array_wr_csn, output reg [15:0] array_wr_raddr, output reg array_caddr_vld_wr, output reg [5:0] array_caddr_wr, output array_wdata_vld, output reg [127:0] array_wdata, input [7:0] array_inner_tras, input [7:0] array_inner_trp, input [7:0] array_inner_trcd_wr, input [7:0] array_inner_twr ); reg [2:0] cur_state,next_state; localparam [2:0] ARR_WR_IDLE = 3'b000; localparam [2:0] ARR_WR_LOWCS = 3'b001; localparam [2:0] ARR_WR_RCD = 3'b010; localparam [2:0] ARR_WR_HIGHVLD = 3'b011; localparam [2:0] ARR_WR_WDATALAST = 3'b100; localparam [2:0] ARR_WR_WDATA = 3'b101; localparam [2:0] ARR_WR_WR = 3'b110; localparam [2:0] ARR_WR_RP = 3'b111; wire wsof,weof; wire [15:0] wraddr; wire [5:0] wcaddr; wire [127:0] wdata; reg [7:0] wr_ras_cnt; reg [7:0] wr_rcd_cnt; reg [7:0] wr_wr_cnt; reg [7:0] wr_rp_cnt; reg single_flag_wr; reg array_wdata_eof; assign {wsof,weof,wraddr,wcaddr,wdata} = array_wr_frame_data; assign array_wdata_vld = !array_caddr_vld_wr; assign array_wr_frame_ready = (cur_state==ARR_WR_IDLE) || ((cur_state == ARR_WR_WDATA) && !array_caddr_vld_wr); assign array_wr_done = (cur_state == ARR_WR_RP) && !wr_rp_cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cur_state <= ARR_WR_IDLE; end else begin cur_state <= next_state; end end always @(*) begin case (cur_state) ARR_WR_IDLE : begin if (array_wr_frame_valid && wsof) begin next_state = ARR_WR_LOWCS; end else begin next_state = ARR_WR_IDLE; end end ARR_WR_LOWCS : begin next_state = ARR_WR_RCD; end ARR_WR_RCD : begin if (wr_rcd_cnt == 'd0) begin next_state = ARR_WR_HIGHVLD; end else begin next_state = ARR_WR_RCD; end end ARR_WR_HIGHVLD : begin if (single_flag_wr) begin next_state = ARR_WR_WDATALAST; end else begin next_state = ARR_WR_WDATA; end end ARR_WR_WDATALAST: begin next_state = ARR_WR_WR; end ARR_WR_WDATA : begin if (array_wdata_eof) begin next_state = ARR_WR_WR; end else begin next_state = ARR_WR_WDATA; end end ARR_WR_WR : begin if (wr_ras_cnt == 'd0 && wr_wr_cnt == 'd0) begin next_state = ARR_WR_RP; end else begin next_state = ARR_WR_WR; end end ARR_WR_RP : begin if (wr_rp_cnt == 'd0) begin next_state = ARR_WR_IDLE; end else begin next_state = ARR_WR_RP; end end default: next_state = ARR_WR_IDLE; endcase end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_wr_csn <= 1'b1; end else if (cur_state == ARR_WR_LOWCS) begin array_wr_csn <= 1'b0; end else if ((cur_state == ARR_WR_WR) && (next_state == ARR_WR_RP)) begin array_wr_csn <= 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_wr_raddr <= 'd0; end else if (array_wr_frame_valid && array_wr_frame_ready) begin array_wr_raddr <= wraddr; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_caddr_wr <= 'd0; end else if (array_wr_frame_valid && array_wr_frame_ready) begin array_caddr_wr <= wcaddr; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_wdata <= 'd0; end else if (array_wr_frame_valid && array_wr_frame_ready) begin array_wdata <= wdata; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_caddr_vld_wr <= 'd0; end else if (array_caddr_vld_wr == 1'b1) begin array_caddr_vld_wr <= 'd0; end else if (cur_state == ARR_WR_HIGHVLD || (cur_state == ARR_WR_WDATA && array_wr_frame_valid && array_wr_frame_ready)) begin array_caddr_vld_wr <= 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_ras_cnt <= 'd0; end else if (cur_state == ARR_WR_LOWCS) begin wr_ras_cnt <= array_inner_tras - 1'b1; end else if (wr_ras_cnt == 'd0) begin wr_ras_cnt <= wr_ras_cnt; end else begin wr_ras_cnt <= wr_ras_cnt - 1'b1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_rcd_cnt <= 'd0; end else if (cur_state == ARR_WR_LOWCS) begin wr_rcd_cnt <= array_inner_trcd_wr - 2'b10; end else if (cur_state == ARR_WR_RCD) begin if (wr_rcd_cnt == 'd0) begin wr_rcd_cnt <= wr_rcd_cnt; end else begin wr_rcd_cnt <= wr_rcd_cnt - 1'b1; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_wr_cnt <= 'd0; end else if (cur_state == ARR_WR_LOWCS) begin wr_wr_cnt <= array_inner_twr -1'b1; end else if (cur_state == ARR_WR_WR) begin if (wr_wr_cnt == 'd0) begin wr_wr_cnt <= wr_wr_cnt; end else begin wr_wr_cnt <= wr_wr_cnt -1'b1; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin wr_rp_cnt <= 'd0; end else if (cur_state == ARR_WR_LOWCS) begin wr_rp_cnt <= array_inner_trp - 1'b1; end else if (cur_state == ARR_WR_RP) begin if (wr_rp_cnt == 'd0) begin wr_rp_cnt <= 'd0; end else begin wr_rp_cnt <= wr_rp_cnt - 1'b1; end end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin single_flag_wr <= 1'b0; end else if (cur_state == ARR_WR_IDLE && array_wr_frame_valid && wsof) begin single_flag_wr <= weof; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin array_wdata_eof <= 'd0; end else if (array_wr_frame_valid && array_wr_frame_ready) begin array_wdata_eof <= weof; end else begin array_wdata_eof <= 'd0; end end endmodule