module wchannel( input clk, input rst_n, input axi_s_awvalid, input [7:0] axi_s_awlen, input [25:0] axi_s_awaddr, output axi_s_awready, input axi_s_wvalid, input axi_s_wlast, input [63:0] axi_s_wdata, output axi_s_wready, output wframe_valid, output [159:0] wframe_data, input wframe_ready ); wire wsof,weof; reg [15:0] wraddr; reg [5:0] wcaddr; wire [127:0] wdata; wire [7:0] awlen; wire [15:0] awraddr; wire [5:0] awcaddr; reg [6:0] wframe_cnt; reg [1:0] cur_state,next_state; localparam [1:0] WCH_IDLE = 2'b01; localparam [1:0] WCH_SD_WADDR = 2'b10; localparam [1:0] WCH_SD_WDATA = 2'b11; wire sync_fifo_aw_wr_en; wire [29:0] sync_fifo_aw_wr_data; wire sync_fifo_aw_rd_en; wire [29:0] sync_fifo_aw_rd_data; wire sync_fifo_aw_full; wire sync_fifo_aw_empty; wire sync_fifo_w_wr_en; wire [63:0] sync_fifo_w_wr_data; wire sync_fifo_w_rd_en; wire [127:0] sync_fifo_w_rd_data; wire sync_fifo_w_full; wire sync_fifo_w_empty; assign sync_fifo_aw_wr_en = axi_s_awvalid && axi_s_awready; assign sync_fifo_aw_wr_data = {axi_s_awaddr[25:4],axi_s_awlen}; assign sync_fifo_aw_rd_en = wframe_ready && weof && !sync_fifo_aw_empty; assign {awraddr,awcaddr,awlen} = sync_fifo_aw_rd_data; assign axi_s_awready = !sync_fifo_aw_full; assign sync_fifo_w_wr_en = axi_s_wvalid && axi_s_wready; assign sync_fifo_w_wr_data = axi_s_wdata; assign sync_fifo_w_rd_en = wframe_valid && wframe_ready; assign wdata = sync_fifo_w_rd_data; assign axi_s_wready = !sync_fifo_w_full; assign wsof = wframe_valid && (wframe_cnt == 7'd0); assign weof = wframe_valid && ((wframe_cnt == awlen >> 1'b1)); assign wframe_data = {wsof,weof,wraddr,wcaddr,wdata,awlen}; assign wframe_valid = !sync_fifo_w_empty && (cur_state == WCH_SD_WDATA); sync_fifo #(.DATA_WIDTH(30), .FIFO_DEPTH(4) ) sync_fifo_aw (.clk (clk), .rst_n (rst_n), .wr_en (sync_fifo_aw_wr_en), .wr_data (sync_fifo_aw_wr_data), .rd_en (sync_fifo_aw_rd_en), .rd_data (sync_fifo_aw_rd_data), .full (sync_fifo_aw_full), .empty (sync_fifo_aw_empty) ); sync_fifo_64_to_128 #( .DATA_IN_WIDTH(64), .DATA_OUT_WIDTH(128), .FIFO_DEPTH(8) ) sync_fifo_w (.clk (clk), .rst_n (rst_n), .wr_en (sync_fifo_w_wr_en), .wr_data (sync_fifo_w_wr_data), .rd_en (sync_fifo_w_rd_en), .rd_data (sync_fifo_w_rd_data), .full (sync_fifo_w_full), .empty (sync_fifo_w_empty) ); always@(posedge clk or negedge rst_n) begin if(!rst_n) begin wframe_cnt <= 'd0; end else if (sync_fifo_w_rd_en) begin if (wframe_cnt == (awlen >> 1'b1)) begin wframe_cnt <= 'd0; end else begin wframe_cnt <= wframe_cnt + 1'b1; end end end always@(posedge clk or negedge rst_n) begin if(!rst_n) begin cur_state <= WCH_IDLE; end else begin cur_state <= next_state; end end always@(*) begin case(cur_state) WCH_IDLE: begin if(sync_fifo_aw_wr_en) begin next_state <= WCH_SD_WADDR; end else begin next_state <= WCH_IDLE; end end WCH_SD_WADDR: begin next_state <= WCH_SD_WDATA; end WCH_SD_WDATA: begin if(sync_fifo_w_rd_en && (wframe_cnt == (awlen >> 1))) begin next_state <= WCH_IDLE; end else begin next_state <= WCH_SD_WDATA; end end default : begin next_state <= WCH_IDLE; end endcase end always@(posedge clk or negedge rst_n) begin if(!rst_n) begin wcaddr <= 'd0; end else if (cur_state == WCH_SD_WADDR) begin wcaddr <= awcaddr; end else if (sync_fifo_w_rd_en) begin if (wcaddr == 6'h3f) begin wcaddr <= 'd0; end else begin wcaddr <= wcaddr + 1'b1; end end end always@(posedge clk or negedge rst_n) begin if(!rst_n) begin wraddr <= 'd0; end else if (cur_state == WCH_SD_WADDR) begin if (sync_fifo_w_rd_en && (wcaddr == 6'h3f)) begin wraddr <= wraddr + 1'b1; end else begin wraddr <= wraddr; end end end endmodule