diff options
author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-14 12:05:07 -0800 |
---|---|---|
committer | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-14 12:05:07 -0800 |
commit | ff1546f8137f7f92bb250f685561b0c34cc0e053 (patch) | |
tree | 7fa6fd05c8828df256a1b20e2935bd3ba9899e2c /fpga/usrp3/lib/zynq_fifo | |
parent | 4f691d88123784c2b405816925f1a1aef69d18c1 (diff) | |
download | uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.tar.gz uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.tar.bz2 uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.zip |
Pushing the bulk of UHD-3.7.0 code.
Diffstat (limited to 'fpga/usrp3/lib/zynq_fifo')
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/.gitignore | 2 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/Makefile.srcs | 15 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/zf_arbiter.v | 199 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/zf_host_to_stream.v | 139 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/zf_slave_readback.v | 91 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/zf_slave_settings.v | 95 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/zf_stream_to_host.v | 149 | ||||
-rw-r--r-- | fpga/usrp3/lib/zynq_fifo/zynq_fifo_top.v | 401 |
8 files changed, 1091 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/zynq_fifo/.gitignore b/fpga/usrp3/lib/zynq_fifo/.gitignore new file mode 100644 index 000000000..40aef90fe --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/.gitignore @@ -0,0 +1,2 @@ +/*.exe +/*.vcd diff --git a/fpga/usrp3/lib/zynq_fifo/Makefile.srcs b/fpga/usrp3/lib/zynq_fifo/Makefile.srcs new file mode 100644 index 000000000..0a63d1627 --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/Makefile.srcs @@ -0,0 +1,15 @@ +# +# Copyright 2012 Ettus Research LLC +# + +################################################## +# ZYNQ FIFO interface sources +################################################## +ZYNQ_FIFO_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/zynq_fifo/, \ +zf_arbiter.v \ +zf_stream_to_host.v \ +zf_host_to_stream.v \ +zf_slave_readback.v \ +zf_slave_settings.v \ +zynq_fifo_top.v \ +)) diff --git a/fpga/usrp3/lib/zynq_fifo/zf_arbiter.v b/fpga/usrp3/lib/zynq_fifo/zf_arbiter.v new file mode 100644 index 000000000..3ee8770ec --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/zf_arbiter.v @@ -0,0 +1,199 @@ +////////////////////////////////////////////////////////////////////////////////// +// Copyright Ettus Research LLC +// The ZYNQ FIFO configuration arbiter: +// - holds configuration memory addresses +// - setting and readback for slave state machines +// - stream of memory addresses for master state machines +////////////////////////////////////////////////////////////////////////////////// + + +module zf_arbiter +#( + parameter STREAMS_WIDTH = 2, + parameter CMDFIFO_DEPTH = 4, + parameter PAGE_WIDTH = 16 +) +( + input clk, + input rst, + + //------------------------------------------------------------------ + //-- settings interface + //------------------------------------------------------------------ + input [31:0] set_addr, + input [31:0] set_data, + input set_stb, + + //------------------------------------------------------------------ + //-- readback interface + //------------------------------------------------------------------ + input [31:0] rb_addr, + output [31:0] rb_data, + input rb_stb, + + //------------------------------------------------------------------ + //-- fifo interactive interface + //------------------------------------------------------------------ + output [71:0] cmd_tdata, + output cmd_tvalid, + input cmd_tready, + input [7:0] sts_tdata, + input sts_tvalid, + output sts_tready, + + //------------------------------------------------------------------ + //-- which stream to process? externally provided + //------------------------------------------------------------------ + input [STREAMS_WIDTH-1:0] ext_stream, + input stream_valid, + + output [31:0] debug +); + +//////////////////////////////////////////////////////////////////////// +///////////////////////////// Begin R T L ////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + localparam NUM_STREAMS = (1 << STREAMS_WIDTH); + + reg [STREAMS_WIDTH-1:0] which_stream; + + //readback mux assignment + reg [31:0] rb_data_i [NUM_STREAMS-1:0]; + assign rb_data = rb_data_i[rb_addr[STREAMS_WIDTH+4:5]]; + + //cmd + sts fifo mux signals + wire [72:0] cmd_data_i [NUM_STREAMS-1:0]; + assign cmd_tdata = cmd_data_i[which_stream]; + wire cmd_tvalid_i [NUM_STREAMS-1:0]; + wire sts_tready_i [NUM_STREAMS-1:0]; + + //////////////////////////////////////////////////////////////////// + // state machine for driving fifo arbitration + //////////////////////////////////////////////////////////////////// + localparam STATE_SET_WHICH_STREAM = 0; + localparam STATE_ASSERT_DO_CMD = 1; + localparam STATE_ASSERT_DO_STS = 2; + localparam STATE_SOME_IDLE = 3; + + reg [1:0] state; + + always @(posedge clk) begin + if (rst) begin + state <= STATE_SET_WHICH_STREAM; + which_stream <= 0; + end + else case (state) + + STATE_SET_WHICH_STREAM: begin + if (cmd_tvalid_i[ext_stream]) state <= STATE_ASSERT_DO_CMD; + which_stream <= ext_stream; + end + + STATE_ASSERT_DO_CMD: begin + if (cmd_tvalid && cmd_tready) state <= STATE_ASSERT_DO_STS; + end + + STATE_ASSERT_DO_STS: begin + if (sts_tvalid && sts_tready) state <= STATE_SOME_IDLE; + end + + STATE_SOME_IDLE: begin + state <= STATE_SET_WHICH_STREAM; + end + + default: state <= STATE_SET_WHICH_STREAM; + + endcase //state + end + + //////////////////////////////////////////////////////////////////// + // memory map + fifos for the host control/status + //////////////////////////////////////////////////////////////////// + + wire do_cmd = (state == STATE_ASSERT_DO_CMD); + wire do_sts = (state == STATE_ASSERT_DO_STS); + + assign cmd_tvalid = do_cmd && cmd_tvalid_i[which_stream]; + assign sts_tready = do_sts && sts_tready_i[which_stream]; + + genvar i; + generate + for (i=0; i < NUM_STREAMS; i=i+1) begin : stream_circuit + + wire [PAGE_WIDTH-3:0] set_addr32 = set_addr[PAGE_WIDTH-1:2]; + wire write_clear = set_stb && (set_addr32 == (0 + i*8)); + wire write_addr = set_stb && (set_addr32 == (1 + i*8)); + wire write_size = set_stb && (set_addr32 == (2 + i*8)); + wire write_sts_rdy = set_stb && (set_addr32 == (3 + i*8)); + wire write_sts = set_stb && (set_addr32 == (4 + i*8)); + + wire [PAGE_WIDTH-3:0] rb_addr32 = rb_addr[PAGE_WIDTH-1:2]; + wire read_sig = (rb_addr32 == (0 + i*8)); + wire read_status = (rb_addr32 == (4 + i*8)); + wire read_sts_occupied = (rb_addr32 == (5 + i*8)); + wire read_cmd_addr_space = (rb_addr32 == (6 + i*8)); + wire read_cmd_size_space = (rb_addr32 == (7 + i*8)); + + wire [15:0] sts_occupied, cmd_addr_space, cmd_size_space; + wire [7:0] sts_readback; + + wire [15:0] this_stream = i; + always @* begin + if (read_sig) rb_data_i[i] <= {16'hACE0, this_stream}; + else if (read_status) rb_data_i[i] <= {24'b0, sts_readback}; + else if (read_sts_occupied) rb_data_i[i] <= {16'b0, sts_occupied}; + else if (read_cmd_addr_space) rb_data_i[i] <= {16'b0, cmd_addr_space}; + else if (read_cmd_size_space) rb_data_i[i] <= {16'b0, cmd_size_space}; + else rb_data_i[i] <= 32'h12345678; + end + + wire [31:0] cmd_addr, cmd_size; + wire cmd_addr_tvalid, cmd_size_tvalid; + assign cmd_data_i[i][32+39:32+36] = 4'b0; //reserved - 0? + assign cmd_data_i[i][32+35:64] = i[3:0]; //tag + assign cmd_data_i[i][63:32] = cmd_addr; + assign cmd_data_i[i][31] = 1'b0; //DRE ReAlignment Request + assign cmd_data_i[i][30] = 1'b1; //always EOF for tlast stream + assign cmd_data_i[i][29:24] = 6'b0; //DRE Stream Alignment + assign cmd_data_i[i][23] = 1'b0; //reserved - 0? + assign cmd_data_i[i][22:0] = cmd_size[22:0]; + + axi_fifo #(.WIDTH(32), .SIZE(CMDFIFO_DEPTH)) crl_addr_fifo + ( + .clk(clk), .reset(rst), .clear(write_clear), + .i_tdata(set_data), .i_tvalid(write_addr), .i_tready(), .space(cmd_addr_space), + .o_tdata(cmd_addr), .o_tvalid(cmd_addr_tvalid), .o_tready(cmd_tready && do_cmd && (which_stream == i)), .occupied() + ); + + axi_fifo #(.WIDTH(32), .SIZE(CMDFIFO_DEPTH)) crl_size_fifo + ( + .clk(clk), .reset(rst), .clear(write_clear), + .i_tdata(set_data), .i_tvalid(write_size), .i_tready(), .space(cmd_size_space), + .o_tdata(cmd_size), .o_tvalid(cmd_size_tvalid), .o_tready(cmd_tready && do_cmd && (which_stream == i)), .occupied() + ); + + assign cmd_tvalid_i[i] = cmd_addr_tvalid && cmd_size_tvalid && stream_valid; + + wire dm_sts_tvalid = sts_tvalid && do_sts && (which_stream == i); + + axi_fifo #(.WIDTH(8), .SIZE(CMDFIFO_DEPTH)) sts_fifo + ( + .clk(clk), .reset(rst), .clear(), + .i_tdata((write_sts)?set_data[7:0]:sts_tdata), .i_tvalid(dm_sts_tvalid || write_sts), .i_tready(sts_tready_i[i]), .space(), + .o_tdata(sts_readback), .o_tvalid(), .o_tready(write_sts_rdy), .occupied(sts_occupied) + ); + + end + endgenerate + + assign debug[1:0] = state; + assign debug[4] = cmd_tvalid; + assign debug[5] = cmd_tready; + assign debug[6] = sts_tvalid; + assign debug[7] = sts_tready; + assign debug[8] = ext_stream; + assign debug[9] = which_stream; + assign debug[15] = rb_addr[STREAMS_WIDTH+4:5]; + +endmodule //zf_arbiter diff --git a/fpga/usrp3/lib/zynq_fifo/zf_host_to_stream.v b/fpga/usrp3/lib/zynq_fifo/zf_host_to_stream.v new file mode 100644 index 000000000..d7ecad158 --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/zf_host_to_stream.v @@ -0,0 +1,139 @@ +////////////////////////////////////////////////////////////////////////////////// +// 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 diff --git a/fpga/usrp3/lib/zynq_fifo/zf_slave_readback.v b/fpga/usrp3/lib/zynq_fifo/zf_slave_readback.v new file mode 100644 index 000000000..f7e25deb2 --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/zf_slave_readback.v @@ -0,0 +1,91 @@ +////////////////////////////////////////////////////////////////////////////////// +// Copyright Ettus Research LLC +// The ZYNQ FIFO slave readback: +// - implements read state machine for 32-bit addressable AXI slave +// - provides readback for state of per-stream fifo pointers +////////////////////////////////////////////////////////////////////////////////// + + +module zf_slave_readback +#( + parameter CONFIG_BASE = 32'h40000000 +) +( + input clk, + input rst, + + //------------------------------------------------------------------ + //-- control read signals - slave + //------------------------------------------------------------------ + input [31:0] AXI_ARADDR, + input AXI_ARVALID, + output AXI_ARREADY, + output [31:0] AXI_RDATA, + output [1:0] AXI_RRESP, + output AXI_RVALID, + input AXI_RREADY, + + //------------------------------------------------------------------ + // readback interface + //------------------------------------------------------------------ + output reg [31:0] addr, + input [31:0] data, + output strobe, + + output [31:0] debug +); + +//////////////////////////////////////////////////////////////////////// +///////////////////////////// Begin R T L ////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + //------------------------------------------------------------------ + // Control read state machine responds to AXI control reads + // Used for reading back the state of the various FIFOs + //------------------------------------------------------------------ + localparam STATE_ADDR = 0; + localparam STATE_READ = 1; + localparam STATE_DATA = 2; + + reg [3:0] state; + + always @(posedge clk) begin + if (rst) begin + state <= STATE_ADDR; + addr <= 0; + end + else case (state) + + STATE_ADDR: begin + if (AXI_ARVALID && AXI_ARREADY) begin + state <= STATE_READ; + addr <= (AXI_ARADDR - CONFIG_BASE); + end + end + + STATE_READ: begin + state <= STATE_DATA; + end + + STATE_DATA: begin + if (AXI_RVALID && AXI_RREADY) begin + state <= STATE_ADDR; + end + end + + default: state <= STATE_ADDR; + + endcase //state + end + + assign strobe = AXI_RVALID && AXI_RREADY; + + //readback data + assign AXI_RDATA = data; + //only acking address reads from the wait state + assign AXI_ARREADY = (state == STATE_ADDR); + //when to release outputs from the slave + assign AXI_RVALID = (state == STATE_DATA); + assign AXI_RRESP = 0; + +endmodule //zf_slave_readback diff --git a/fpga/usrp3/lib/zynq_fifo/zf_slave_settings.v b/fpga/usrp3/lib/zynq_fifo/zf_slave_settings.v new file mode 100644 index 000000000..026845682 --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/zf_slave_settings.v @@ -0,0 +1,95 @@ +////////////////////////////////////////////////////////////////////////////////// +// Copyright Ettus Research LLC +// The ZYNQ FIFO slave settings: +// - implements write state machine for 32-bit addressable AXI slave +// - provides settings for state of per-stream fifo pointers +// - implements configuration of FIFO's physical DDR addresses +////////////////////////////////////////////////////////////////////////////////// + + +module zf_slave_settings +#( + parameter CONFIG_BASE = 32'h40000000 +) +( + input clk, + input rst, + + //------------------------------------------------------------------ + //-- control write signals - slave + //------------------------------------------------------------------ + input [31:0] AXI_AWADDR, + input AXI_AWVALID, + output AXI_AWREADY, + input [31:0] AXI_WDATA, + input [3:0] AXI_WSTRB, + input AXI_WVALID, + output AXI_WREADY, + output [1:0] AXI_BRESP, + output AXI_BVALID, + input AXI_BREADY, + + //------------------------------------------------------------------ + // settings interface + //------------------------------------------------------------------ + output reg [31:0] addr, + output reg [31:0] data, + output strobe, + + output [31:0] debug +); + +//////////////////////////////////////////////////////////////////////// +///////////////////////////// Begin R T L ////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + //------------------------------------------------------------------ + // Control write state machine responds to AXI control writes + // Used for setting the state of the various FIFOs + //------------------------------------------------------------------ + localparam STATE_ADDR = 0; + localparam STATE_DATA = 1; + localparam STATE_WRITE = 2; + + reg [1:0] state; + + always @(posedge clk) begin + if (rst) begin + state <= STATE_ADDR; + addr <= 0; + data <= 0; + end + else case (state) + + STATE_ADDR: begin + if (AXI_AWVALID && AXI_AWREADY) begin + addr <= (AXI_AWADDR - CONFIG_BASE); + state <= STATE_DATA; + end + end + + STATE_DATA: begin + if (AXI_WVALID && AXI_WREADY) begin + data <= AXI_WDATA; + state <= STATE_WRITE; + end + end + + STATE_WRITE: begin + state <= STATE_ADDR; + end + + default: state <= STATE_ADDR; + + endcase //state + end + + assign strobe = (state == STATE_WRITE); + + //assign to slave write + assign AXI_AWREADY = (state == STATE_ADDR); + assign AXI_WREADY = (state == STATE_DATA); + assign AXI_BRESP = 0; + assign AXI_BVALID = AXI_BREADY; //FIXME - we can choose not to assert valid + +endmodule //zf_slave_settings diff --git a/fpga/usrp3/lib/zynq_fifo/zf_stream_to_host.v b/fpga/usrp3/lib/zynq_fifo/zf_stream_to_host.v new file mode 100644 index 000000000..246d43dab --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/zf_stream_to_host.v @@ -0,0 +1,149 @@ +////////////////////////////////////////////////////////////////////////////////// +// Copyright Ettus Research LLC +// 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 diff --git a/fpga/usrp3/lib/zynq_fifo/zynq_fifo_top.v b/fpga/usrp3/lib/zynq_fifo/zynq_fifo_top.v new file mode 100644 index 000000000..7b7ffbd16 --- /dev/null +++ b/fpga/usrp3/lib/zynq_fifo/zynq_fifo_top.v @@ -0,0 +1,401 @@ +`timescale 1ns / 1ps + +////////////////////////////////////////////////////////////////////////////////// +// Copyright Ettus Research LLC +// The ZYNQ FIFO Top: +// - takes read and write 32-bit addressable AXI slave +// - takes read and write 64-bit addressable AXI master +// - drives N input and output AXI stream FIFOs +////////////////////////////////////////////////////////////////////////////////// + +// Mapping: +// Page0 - stream to host config +// Page1 - host to stream config + +module zynq_fifo_top +#( + parameter CONFIG_BASE = 32'h40000000, + parameter PAGE_WIDTH = 16, //in bytes, must fit widths below + parameter H2S_STREAMS_WIDTH = 2, + parameter H2S_CMDFIFO_DEPTH = 4, + parameter S2H_STREAMS_WIDTH = 2, + parameter S2H_CMDFIFO_DEPTH = 4, + parameter PROT = 3'b010 //data, non-secure, unpriv +) +( + input clk, + input rst, + + //------------------------------------------------------------------ + // AXI slave addressable signals - control + //------------------------------------------------------------------ + //control write signals - slave + input [31:0] CTL_AXI_AWADDR, + input CTL_AXI_AWVALID, + output CTL_AXI_AWREADY, + input [31:0] CTL_AXI_WDATA, + input [3:0] CTL_AXI_WSTRB, + input CTL_AXI_WVALID, + output CTL_AXI_WREADY, + output [1:0] CTL_AXI_BRESP, + output CTL_AXI_BVALID, + input CTL_AXI_BREADY, + + //control read signals - slave + input [31:0] CTL_AXI_ARADDR, + input CTL_AXI_ARVALID, + output CTL_AXI_ARREADY, + output [31:0] CTL_AXI_RDATA, + output [1:0] CTL_AXI_RRESP, + output CTL_AXI_RVALID, + input CTL_AXI_RREADY, + + //------------------------------------------------------------------ + // AXI master addressable signals - DDR access + //------------------------------------------------------------------ + //memory write signals - master + output [31:0] DDR_AXI_AWADDR, + output [2:0] DDR_AXI_AWPROT, + output DDR_AXI_AWVALID, + input DDR_AXI_AWREADY, + output [63:0] DDR_AXI_WDATA, + output [7:0] DDR_AXI_WSTRB, + output DDR_AXI_WVALID, + input DDR_AXI_WREADY, + input [1:0] DDR_AXI_BRESP, + input DDR_AXI_BVALID, + output DDR_AXI_BREADY, + output [7:0] DDR_AXI_AWLEN, + output [2:0] DDR_AXI_AWSIZE, + output [1:0] DDR_AXI_AWBURST, + output [3:0] DDR_AXI_AWCACHE, + output DDR_AXI_WLAST, + + //memory read signals - master + output [31:0] DDR_AXI_ARADDR, + output [2:0] DDR_AXI_ARPROT, + output DDR_AXI_ARVALID, + input DDR_AXI_ARREADY, + input [63:0] DDR_AXI_RDATA, + input [1:0] DDR_AXI_RRESP, + input DDR_AXI_RVALID, + output DDR_AXI_RREADY, + input DDR_AXI_RLAST, + output [3:0] DDR_AXI_ARCACHE, + output [7:0] DDR_AXI_ARLEN, + output [1:0] DDR_AXI_ARBURST, + output [2:0] DDR_AXI_ARSIZE, + + //------------------------------------------------------------------ + // AXI streams host to stream + //------------------------------------------------------------------ + output [63:0] h2s_tdata, + output h2s_tlast, + output h2s_tvalid, + input h2s_tready, + + //------------------------------------------------------------------ + // AXI streams stream to host + //------------------------------------------------------------------ + input [63:0] s2h_tdata, + input s2h_tlast, + input s2h_tvalid, + output s2h_tready, + + output event_irq, + + output [31:0] debug +); + +//////////////////////////////////////////////////////////////////////// +///////////////////////////// Begin R T L ////////////////////////////// +//////////////////////////////////////////////////////////////////////// + + //interrupt wires + wire h2s_irq, s2h_irq; + assign event_irq = h2s_irq | s2h_irq; + + wire [31:0] set_addr, set_data; + wire [31:0] rb_addr, rb_data; + wire [31:0] rb_data_s2h, rb_data_h2s; + wire set_stb, set_stb_s2h, set_stb_h2s; + wire rb_stb, rb_stb_s2h, rb_stb_h2s; + + wire [1:0] set_page = set_addr[PAGE_WIDTH+1:PAGE_WIDTH]; + wire [1:0] rb_page = rb_addr[PAGE_WIDTH+1:PAGE_WIDTH]; + + //each arbiter gets 1 page + assign set_stb_s2h = set_stb && (set_page == 2'h0); + assign set_stb_h2s = set_stb && (set_page == 2'h1); + assign rb_stb_s2h = rb_stb && (rb_page == 2'h0); + assign rb_stb_h2s = rb_stb && (rb_page == 2'h1); + assign rb_data = (rb_page == 2'h0)? rb_data_s2h : rb_data_h2s; + + //------------------------------------------------------------------ + // configuration slaves + //------------------------------------------------------------------ + zf_slave_settings #(.CONFIG_BASE(CONFIG_BASE)) zf_slave_settings + ( + .clk(clk), .rst(rst), + .AXI_AWADDR(CTL_AXI_AWADDR), + .AXI_AWVALID(CTL_AXI_AWVALID), + .AXI_AWREADY(CTL_AXI_AWREADY), + .AXI_WDATA(CTL_AXI_WDATA), + .AXI_WSTRB(CTL_AXI_WSTRB), + .AXI_WVALID(CTL_AXI_WVALID), + .AXI_WREADY(CTL_AXI_WREADY), + .AXI_BRESP(CTL_AXI_BRESP), + .AXI_BVALID(CTL_AXI_BVALID), + .AXI_BREADY(CTL_AXI_BREADY), + .addr(set_addr), .data(set_data), .strobe(set_stb), + .debug() + ); + zf_slave_readback #(.CONFIG_BASE(CONFIG_BASE)) zf_slave_readback + ( + .clk(clk), .rst(rst), + .AXI_ARADDR(CTL_AXI_ARADDR), + .AXI_ARVALID(CTL_AXI_ARVALID), + .AXI_ARREADY(CTL_AXI_ARREADY), + .AXI_RDATA(CTL_AXI_RDATA), + .AXI_RRESP(CTL_AXI_RRESP), + .AXI_RVALID(CTL_AXI_RVALID), + .AXI_RREADY(CTL_AXI_RREADY), + .addr(rb_addr), .data(rb_data), .strobe(rb_stb), + .debug() + ); + + //------------------------------------------------------------------ + // fifo to ddr + //------------------------------------------------------------------ + wire [71:0] s2h_cmd_tdata; + wire [7:0] s2h_sts_tdata; + wire s2h_cmd_tvalid, s2h_cmd_tready; + wire s2h_sts_tvalid, s2h_sts_tready; + + assign s2h_irq = s2h_sts_tvalid; + + //lookup destination + wire [63:0] s2h_tdata_i0; + wire s2h_tready_i0, s2h_tvalid_i0, s2h_tlast_i0; + wire [S2H_STREAMS_WIDTH-1:0] which_stream_s2h; + + cvita_dest_lookup #(.DEST_WIDTH(S2H_STREAMS_WIDTH)) s2h_dest_gen + ( + .clk(clk), .rst(rst), + .set_stb(set_stb && (set_page == 2'h2)), .set_addr(set_addr[9:2]), .set_data(set_data), + .i_tdata(s2h_tdata), .i_tlast(s2h_tlast), .i_tvalid(s2h_tvalid), .i_tready(s2h_tready), + .o_tdata(s2h_tdata_i0), .o_tlast(s2h_tlast_i0), .o_tvalid(s2h_tvalid_i0), .o_tready(s2h_tready_i0), + .o_tdest(which_stream_s2h) + ); + + //only active in cycles between command and tlast + //this prevents bullshit consumption after tlast + reg s2h_active; + always @(posedge clk) begin + if (rst) s2h_active <= 0; + else if (s2h_cmd_tvalid && s2h_cmd_tready) s2h_active <= 1; + else if (s2h_tready_i0 && s2h_tvalid_i0 && s2h_tlast_i0) s2h_active <= 0; + end + + //cut fifo comms when not in active state + wire [63:0] s2h_tdata_i1; + wire s2h_tready_i1, s2h_tvalid_i1, s2h_tlast_i1; + assign s2h_tdata_i1 = s2h_tdata_i0; + assign s2h_tlast_i1 = s2h_tlast_i0; + assign s2h_tvalid_i1 = s2h_tvalid_i0 && s2h_active; + assign s2h_tready_i0 = s2h_tready_i1 && s2h_active; + + wire [31:0] s2h_arbiter_debug; + zf_arbiter #( + .STREAMS_WIDTH(H2S_STREAMS_WIDTH), + .CMDFIFO_DEPTH(H2S_CMDFIFO_DEPTH), + .PAGE_WIDTH(PAGE_WIDTH) + ) s2h_arbiter + ( + .clk(clk), .rst(rst), + .set_addr(set_addr), .set_data(set_data), .set_stb(set_stb_s2h), + .rb_addr(rb_addr), .rb_data(rb_data_s2h), .rb_stb(rb_stb_s2h), + .cmd_tdata(s2h_cmd_tdata), .cmd_tvalid(s2h_cmd_tvalid), .cmd_tready(s2h_cmd_tready), + .sts_tdata(s2h_sts_tdata), .sts_tvalid(s2h_sts_tvalid), .sts_tready(s2h_sts_tready), + .ext_stream(which_stream_s2h), .stream_valid(s2h_tvalid_i0), + .debug(s2h_arbiter_debug) + ); + + //------------------------------------------------------------------ + // ddr to fifo + //------------------------------------------------------------------ + wire [71:0] h2s_cmd_tdata; + wire [7:0] h2s_sts_tdata; + wire h2s_cmd_tvalid, h2s_cmd_tready; + wire h2s_sts_tvalid, h2s_sts_tready; + + assign h2s_irq = h2s_sts_tvalid; + + //simple round robin implementation for checking available packets + reg [H2S_STREAMS_WIDTH-1:0] which_stream_h2s; + always @(posedge clk) + if (rst) which_stream_h2s <= 0; + else which_stream_h2s <= which_stream_h2s + 1'b1; + + wire [31:0] h2s_arbiter_debug; + zf_arbiter #( + .STREAMS_WIDTH(S2H_STREAMS_WIDTH), + .CMDFIFO_DEPTH(S2H_CMDFIFO_DEPTH), + .PAGE_WIDTH(PAGE_WIDTH) + ) h2s_arbiter + ( + .clk(clk), .rst(rst), + .set_addr(set_addr), .set_data(set_data), .set_stb(set_stb_h2s), + .rb_addr(rb_addr), .rb_data(rb_data_h2s), .rb_stb(rb_stb_h2s), + .cmd_tdata(h2s_cmd_tdata), .cmd_tvalid(h2s_cmd_tvalid), .cmd_tready(h2s_cmd_tready), + .sts_tdata(h2s_sts_tdata), .sts_tvalid(h2s_sts_tvalid), .sts_tready(h2s_sts_tready), + .ext_stream(which_stream_h2s), .stream_valid(1'b1), + .debug(h2s_arbiter_debug) + ); + + //------------------------------------------------------------------ + // axi_datamover + //------------------------------------------------------------------ + wire reset_dm = rst; + axi_datamover_v3_00_a axi_datamover + ( + //host to stream reset stuff + .m_axi_mm2s_aclk(clk), + .m_axi_mm2s_aresetn(!reset_dm), + .mm2s_halt(1'b0), + .mm2s_halt_cmplt(), + .mm2s_err(), + + //host to stream command + .m_axis_mm2s_cmdsts_aclk(clk), + .m_axis_mm2s_cmdsts_aresetn(!reset_dm), + .s_axis_mm2s_cmd_tvalid(h2s_cmd_tvalid), + .s_axis_mm2s_cmd_tready(h2s_cmd_tready), + .s_axis_mm2s_cmd_tdata(h2s_cmd_tdata), + + //host to stream status + .m_axis_mm2s_sts_tvalid(h2s_sts_tvalid), + .m_axis_mm2s_sts_tready(h2s_sts_tready), + .m_axis_mm2s_sts_tdata(h2s_sts_tdata), + .m_axis_mm2s_sts_tkeep(), + .m_axis_mm2s_sts_tlast(), + + //store and forward - always can post + .mm2s_allow_addr_req(1'b1), + .mm2s_addr_req_posted(), + .mm2s_rd_xfer_cmplt(), + + //HP RD connection to DDR + .m_axi_mm2s_arid(), + .m_axi_mm2s_araddr(DDR_AXI_ARADDR), + .m_axi_mm2s_arlen(DDR_AXI_ARLEN), + .m_axi_mm2s_arsize(DDR_AXI_ARSIZE), + .m_axi_mm2s_arburst(DDR_AXI_ARBURST), + .m_axi_mm2s_arprot(DDR_AXI_ARPROT), + .m_axi_mm2s_arcache(DDR_AXI_ARCACHE), + .m_axi_mm2s_arvalid(DDR_AXI_ARVALID), + .m_axi_mm2s_arready(DDR_AXI_ARREADY), + .m_axi_mm2s_rdata(DDR_AXI_RDATA), + .m_axi_mm2s_rresp(DDR_AXI_RRESP), + .m_axi_mm2s_rlast(DDR_AXI_RLAST), + .m_axi_mm2s_rvalid(DDR_AXI_RVALID), + .m_axi_mm2s_rready(DDR_AXI_RREADY), + + //AXI host to stream connection + .m_axis_mm2s_tdata({h2s_tdata[31:0], h2s_tdata[63:32]}), + .m_axis_mm2s_tkeep(), //dont care + .m_axis_mm2s_tlast(h2s_tlast), + .m_axis_mm2s_tvalid(h2s_tvalid), + .m_axis_mm2s_tready(h2s_tready), + + //unused debug + .mm2s_dbg_sel(4'b0), + .mm2s_dbg_data(), + + //stream to host reset stuff + .m_axi_s2mm_aclk(clk), + .m_axi_s2mm_aresetn(!reset_dm), + .s2mm_halt(1'b0), + .s2mm_halt_cmplt(), + .s2mm_err(), + + //stream to host command + .m_axis_s2mm_cmdsts_awclk(clk), + .m_axis_s2mm_cmdsts_aresetn(!reset_dm), + .s_axis_s2mm_cmd_tvalid(s2h_cmd_tvalid), + .s_axis_s2mm_cmd_tready(s2h_cmd_tready), + .s_axis_s2mm_cmd_tdata(s2h_cmd_tdata), + + //stream to host status + .m_axis_s2mm_sts_tvalid(s2h_sts_tvalid), + .m_axis_s2mm_sts_tready(s2h_sts_tready), + .m_axis_s2mm_sts_tdata(s2h_sts_tdata), + .m_axis_s2mm_sts_tkeep(), + .m_axis_s2mm_sts_tlast(), + + //store and forward - always can post + .s2mm_allow_addr_req(1'b1), + .s2mm_addr_req_posted(), + .s2mm_wr_xfer_cmplt(), + .s2mm_ld_nxt_len(), + .s2mm_wr_len(), + + //HP WR connection to DDR + .m_axi_s2mm_awid(), + .m_axi_s2mm_awaddr(DDR_AXI_AWADDR), + .m_axi_s2mm_awlen(DDR_AXI_AWLEN), + .m_axi_s2mm_awsize(DDR_AXI_AWSIZE), + .m_axi_s2mm_awburst(DDR_AXI_AWBURST), + .m_axi_s2mm_awprot(DDR_AXI_AWPROT), + .m_axi_s2mm_awcache(DDR_AXI_AWCACHE), + .m_axi_s2mm_awvalid(DDR_AXI_AWVALID), + .m_axi_s2mm_awready(DDR_AXI_AWREADY), + .m_axi_s2mm_wdata(DDR_AXI_WDATA), + .m_axi_s2mm_wstrb(DDR_AXI_WSTRB), + .m_axi_s2mm_wlast(DDR_AXI_WLAST), + .m_axi_s2mm_wvalid(DDR_AXI_WVALID), + .m_axi_s2mm_wready(DDR_AXI_WREADY), + .m_axi_s2mm_bresp(DDR_AXI_BRESP), + .m_axi_s2mm_bvalid(DDR_AXI_BVALID), + .m_axi_s2mm_bready(DDR_AXI_BREADY), + + //AXI stream to host connection + .s_axis_s2mm_tdata({s2h_tdata_i1[31:0], s2h_tdata_i1[63:32]}), + .s_axis_s2mm_tkeep(8'hff), //all bytes valid + .s_axis_s2mm_tlast(s2h_tlast_i1), + .s_axis_s2mm_tvalid(s2h_tvalid_i1), + .s_axis_s2mm_tready(s2h_tready_i1), + + //unused debug + .s2mm_dbg_sel(4'b0), + .s2mm_dbg_data() + ); + + //------------------------------------------------------------------ + // chipscope debugs + //------------------------------------------------------------------ + wire [35:0] CONTROL; + wire [255:0] DATA; + wire [7:0] TRIG; + + chipscope_icon chipscope_icon(.CONTROL0(CONTROL)); + + chipscope_ila chipscope_ila + ( + .CONTROL(CONTROL), .CLK(clk), + .DATA(DATA), .TRIG0(TRIG) + ); + + assign DATA[255:256-64] = {set_addr, set_data}; + assign DATA[79:76] = which_stream_s2h; + assign DATA[75:72] = {1'b0, s2h_tlast, s2h_tvalid, s2h_tready}; + assign DATA[71:68] = {1'b0, s2h_tlast_i0, s2h_tvalid_i0, s2h_tready_i0}; + assign DATA[67:64] = {1'b0, s2h_tlast_i1, s2h_tvalid_i1, s2h_tready_i1}; + assign DATA[63:0] = s2h_tdata_i1; + + assign TRIG = { + set_stb, s2h_tlast_i0, s2h_tvalid_i0, s2h_tready_i0, + (set_stb && (set_page == 2'h2)), s2h_tlast_i1, s2h_tvalid_i1, s2h_tready_i1 + }; + +endmodule //zynq_fifo_top |