////////////////////////////////////////////////////////////////////////////////// // // Copyright Ettus Research LLC // Copyright 2014 Ettus Research, a National Instruments Company // // SPDX-License-Identifier: LGPL-3.0-or-later // // The ZYNQ FIFO - read FIFO and write to DDR: // - implements write state machine for AXI master on DDR // - provides input fifos from external fabric ////////////////////////////////////////////////////////////////////////////////// //This implementation takes many states to do individual //64 bit xfers from FIFO to the AXI write master. //TODO: use axi 4/full with busts, //in this case we should be able to directly connect the fifo //to the write lines with much less state machinery. module zf_stream_to_host #( parameter PROT = 3'b010, //data, non-secure, unpriv parameter STRB = 4'b1111 //write all bytes ) ( input clk, input rst, input enb, //------------------------------------------------------------------ //-- DDR write signals - master //------------------------------------------------------------------ output [31:0] AXI_AWADDR, output [2:0] AXI_AWPROT, output AXI_AWVALID, input AXI_AWREADY, output [63:0] AXI_WDATA, output [3:0] AXI_WSTRB, output AXI_WVALID, input AXI_WREADY, input [1:0] AXI_BRESP, input AXI_BVALID, output AXI_BREADY, //------------------------------------------------------------------ // FIFO streaming interfaces //------------------------------------------------------------------ input [63:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, //------------------------------------------------------------------ // configuration interface //------------------------------------------------------------------ input [31:0] mem_addr, input mem_valid, output mem_ack, output [31:0] debug ); //////////////////////////////////////////////////////////////////////// ///////////////////////////// Begin R T L ////////////////////////////// //////////////////////////////////////////////////////////////////////// localparam STATE_WAIT_MEM = 0; localparam STATE_READ_LINE = 1; localparam STATE_WRITE_ADDR = 2; localparam STATE_WRITE_DATA = 3; localparam STATE_WRITE_B = 4; localparam STATE_DONE = 5; reg [31:0] base_addr; reg [63:0] line; reg last; reg [2:0] state; always @(posedge clk) begin if (rst) begin state <= STATE_WAIT_MEM; base_addr <= 0; line <= 0; last <= 0; end else if (enb) case (state) STATE_WAIT_MEM: begin if (mem_valid) begin state <= STATE_READ_LINE; end base_addr <= mem_addr; end STATE_READ_LINE: begin if (i_tvalid && i_tready) begin line <= i_tdata; last <= i_tlast; state <= STATE_WRITE_ADDR; end end STATE_WRITE_ADDR: begin if (AXI_AWVALID && AXI_AWREADY) begin state <= STATE_WRITE_DATA; end end STATE_WRITE_DATA: begin if (AXI_WVALID && AXI_WREADY) begin state <= STATE_WRITE_B; end end STATE_WRITE_B: begin if (AXI_BREADY && AXI_BVALID) begin//FIXME, slave may not assert valid if (last) state <= STATE_DONE; else state <= STATE_READ_LINE; base_addr <= base_addr + 32'h8; end end STATE_DONE: begin state <= STATE_WAIT_MEM; end default: state <= STATE_WAIT_MEM; endcase //state end assign i_tready = (state == STATE_READ_LINE); assign mem_ack = (state == STATE_DONE); //assign to master write assign AXI_AWVALID = (state == STATE_WRITE_ADDR); assign AXI_WVALID = (state == STATE_WRITE_DATA); assign AXI_AWADDR = base_addr; assign AXI_WDATA = {line[31:0], line[63:32]}; assign AXI_WSTRB = STRB; assign AXI_AWPROT = PROT; assign AXI_BREADY = (state == STATE_WRITE_B); assign debug[2:0] = state; assign debug[4] = mem_valid; assign debug[5] = mem_ack; assign debug[6] = AXI_AWVALID; assign debug[7] = AXI_AWREADY; assign debug[8] = AXI_WVALID; assign debug[9] = AXI_WREADY; assign debug[10] = AXI_BVALID; assign debug[11] = AXI_BREADY; endmodule //zf_stream_to_host