////////////////////////////////////////////////////////////////////////////////// // Copyright Ettus Research LLC // The ZYNQ FIFO - read DDR and write to FIFO: // - implements read state machine for AXI master on DDR // - provides output fifos to external fabric ////////////////////////////////////////////////////////////////////////////////// module zf_host_to_stream #( parameter PROT = 3'b010 //data, non-secure, unpriv ) ( input clk, input rst, input enb, //------------------------------------------------------------------ //-- DDR read signals - master //------------------------------------------------------------------ output [31:0] AXI_ARADDR, output [2:0] AXI_ARPROT, output AXI_ARVALID, input AXI_ARREADY, input [63:0] AXI_RDATA, input [1:0] AXI_RRESP, input AXI_RVALID, output AXI_RREADY, //------------------------------------------------------------------ // FIFO streaming interfaces //------------------------------------------------------------------ output [63:0] o_tdata, output o_tlast, output o_tvalid, input o_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_WRITE_ADDR = 1; localparam STATE_READ_DATA = 2; localparam STATE_WRITE_LINE = 3; localparam STATE_DONE = 4; reg [31:0] base_addr; reg [63:0] line; reg [15:0] line32_count; reg first_line; reg [2:0] state; always @(posedge clk) begin if (rst) begin state <= STATE_WAIT_MEM; base_addr <= 0; line <= 0; line32_count <= 0; first_line <= 1; end else if (enb) case (state) STATE_WAIT_MEM: begin if (mem_valid) begin state <= STATE_WRITE_ADDR; end base_addr <= mem_addr; first_line <= 1; end STATE_WRITE_ADDR: begin if (AXI_ARVALID && AXI_ARREADY) begin state <= STATE_READ_DATA; end end STATE_READ_DATA: begin if (AXI_RVALID && AXI_RREADY) begin line <= AXI_RDATA; state <= STATE_WRITE_LINE; if (first_line) begin //round up to multiple of 64 minus one line //Note! words32 are swapped here, inspect lower for length line32_count <= AXI_RDATA[15:0] - 16'b1; first_line <= 0; end end end STATE_WRITE_LINE: begin if (o_tvalid && o_tready) begin if (o_tlast) state <= STATE_DONE; else state <= STATE_WRITE_ADDR; base_addr <= base_addr + 32'h8; line32_count <= line32_count - 16'h2; end end STATE_DONE: begin state <= STATE_WAIT_MEM; end default: state <= STATE_WAIT_MEM; endcase //state end assign o_tdata = {line[31:0], line[63:32]}; assign o_tlast = (line32_count[15:1] == 15'b0); //ignore low bit assign o_tvalid = (state == STATE_WRITE_LINE); assign mem_ack = (state == STATE_DONE); //the master read address always comes from the reg assign AXI_ARADDR = base_addr; assign AXI_ARVALID = (state == STATE_WRITE_ADDR); assign AXI_RREADY = (state == STATE_READ_DATA); assign AXI_ARPROT = PROT; assign debug[2:0] = state; assign debug[3] = first_line; assign debug[4] = mem_valid; assign debug[5] = mem_ack; assign debug[6] = AXI_ARVALID; assign debug[7] = AXI_ARREADY; assign debug[8] = AXI_RVALID; assign debug[9] = AXI_RREADY; endmodule //zf_host_to_stream