diff options
Diffstat (limited to 'fpga/usrp3/lib/control/axi_setting_reg.v')
-rw-r--r-- | fpga/usrp3/lib/control/axi_setting_reg.v | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/axi_setting_reg.v b/fpga/usrp3/lib/control/axi_setting_reg.v new file mode 100644 index 000000000..9d419ec32 --- /dev/null +++ b/fpga/usrp3/lib/control/axi_setting_reg.v @@ -0,0 +1,97 @@ +// +// Copyright 2016 Ettus Research +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Settings register with AXI stream output. +// +// Parameters / common use cases: +// USE_ADDR_LAST & ADDR_LAST User wants additional address that when written to asserts tlast. +// Useful for the last word in a packet. +// USE_FIFO & FIFO_SIZE Downstream block can throttle and a FIFO is needed to handle that case. +// STROBE_LAST User always wants to assert tlast on writes. More efficient than USE_ADDR_LAST +// since only one address is used instead of two. +// REPEATS Keep tvalid asserted after initial write. +// STROBE_LAST & REPEATS tlast is asserted on the initial write then deasserted for repeating output. +// MSB_ALIGN Left justify data versus right justify. + +module axi_setting_reg #( + parameter ADDR = 0, + parameter USE_ADDR_LAST = 0, + parameter ADDR_LAST = ADDR+1, + parameter AWIDTH = 8, + parameter WIDTH = 32, + parameter USE_FIFO = 0, + parameter FIFO_SIZE = 5, + parameter DATA_AT_RESET = 0, + parameter VALID_AT_RESET = 0, + parameter LAST_AT_RESET = 0, + parameter STROBE_LAST = 0, + parameter REPEATS = 0, + parameter MSB_ALIGN = 0 +) +( + input clk, input reset, output reg error_stb, + input set_stb, input [AWIDTH-1:0] set_addr, input [31:0] set_data, + output [WIDTH-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready +); + + reg init; + + reg [WIDTH-1:0] o_tdata_int; + reg o_tlast_int, o_tvalid_int; + wire o_tready_int; + + always @(posedge clk) begin + if (reset) begin + o_tdata_int <= DATA_AT_RESET; + o_tvalid_int <= VALID_AT_RESET; + o_tlast_int <= LAST_AT_RESET; + init <= 1'b0; + error_stb <= 1'b0; + end else begin + error_stb <= 1'b0; + if (o_tvalid_int & o_tready_int) begin + // Deassert tvalid / tlast only if not repeating the output + if (REPEATS == 0) begin + o_tvalid_int <= 1'b0; + end + if ((REPEATS == 0) | (STROBE_LAST == 1)) begin + o_tlast_int <= 1'b0; + end + end + if (set_stb & ((ADDR[AWIDTH-1:0] == set_addr) | (USE_ADDR_LAST & (ADDR_LAST[AWIDTH-1:0] == set_addr)))) begin + init <= 1'b1; + o_tdata_int <= (MSB_ALIGN == 0) ? set_data[WIDTH-1:0] : set_data[31:32-WIDTH]; + o_tvalid_int <= 1'b1; + if (set_stb & (STROBE_LAST | (USE_ADDR_LAST & (ADDR_LAST[AWIDTH-1:0] == set_addr)))) begin + o_tlast_int <= 1'b1; + end else begin + o_tlast_int <= 1'b0; + end + if (~o_tready_int) begin + error_stb <= 1'b1; + end + end + end + end + + generate + if (USE_FIFO) begin + axi_fifo #( + .WIDTH(WIDTH+1), .SIZE(FIFO_SIZE)) + axi_fifo ( + .clk(clk), .reset(reset), .clear(1'b0), + .i_tdata({o_tlast_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int), + .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready), + .space(), .occupied()); + end else begin + assign o_tdata = o_tdata_int; + assign o_tlast = o_tlast_int; + assign o_tvalid = o_tvalid_int; + assign o_tready_int = o_tready; + end + endgenerate + +endmodule |