diff options
Diffstat (limited to 'fpga/usrp3/lib/control/axil_to_ni_regport.v')
-rw-r--r-- | fpga/usrp3/lib/control/axil_to_ni_regport.v | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/control/axil_to_ni_regport.v b/fpga/usrp3/lib/control/axil_to_ni_regport.v new file mode 100644 index 000000000..876991ed9 --- /dev/null +++ b/fpga/usrp3/lib/control/axil_to_ni_regport.v @@ -0,0 +1,164 @@ +// +// Copyright 2016 Ettus Research +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// AXI4lite to NI Register Port interface +// + +module axil_to_ni_regport #( + parameter RP_AWIDTH = 16, + parameter RP_DWIDTH = 32, + parameter TIMEOUT = 512 +)( + input s_axi_aclk, + input s_axi_areset, + + // AXI4lite interface + input [31:0] s_axi_awaddr, + input s_axi_awvalid, + output s_axi_awready, + input [31:0] s_axi_wdata, + input [3:0] s_axi_wstrb, + input s_axi_wvalid, + output s_axi_wready, + output [1:0] s_axi_bresp, + output s_axi_bvalid, + input s_axi_bready, + input [31:0] s_axi_araddr, + input s_axi_arvalid, + output s_axi_arready, + output [31:0] s_axi_rdata, + output [1:0] s_axi_rresp, + output s_axi_rvalid, + input s_axi_rready, + + // RegPort interface, the out vs in + // is seen from the slave device + // hooked up to the regport + output reg_port_in_rd, + output reg_port_in_wt, + output [RP_AWIDTH-1:0] reg_port_in_addr, + output [RP_DWIDTH-1:0] reg_port_in_data, + input [RP_DWIDTH-1:0] reg_port_out_data, + input reg_port_out_ready +); + + localparam IDLE = 3'd0; + localparam READ_INIT = 3'd1; + localparam WRITE_INIT = 3'd2; + localparam READ_IN_PROGRESS = 3'd3; + localparam WRITE_IN_PROGRESS = 3'd4; + localparam WRITE_DONE = 3'd5; + localparam READ_DONE = 3'd6; + + reg [RP_AWIDTH-1:0] addr; + reg [RP_DWIDTH-1:0] rb_data; + reg [RP_DWIDTH-1:0] wr_data; + reg [2:0] state; + reg [9:0] count; + reg [1:0] rresp; + reg [1:0] bresp; + + always @ (posedge s_axi_aclk) begin + if (s_axi_areset) begin + state <= IDLE; + addr <= 'd0; + rb_data <= 'd0; + wr_data <= 'd0; + + count <= 10'd0; + rresp <= 2'd0; + bresp <= 2'd0; + end + else case (state) + + IDLE: begin + if (s_axi_arvalid) begin + state <= READ_INIT; + addr <= s_axi_araddr[RP_AWIDTH-1:0]; + end + else if (s_axi_awvalid) begin + state <= WRITE_INIT; + addr <= s_axi_awaddr[RP_AWIDTH-1:0]; + end + end + + READ_INIT: begin + state <= READ_IN_PROGRESS; + count <= 10'd0; + rresp <= 2'b00; + end + + READ_IN_PROGRESS: begin + if (reg_port_out_ready) begin + rb_data <= reg_port_out_data; + state <= READ_DONE; + end + else if (count >= TIMEOUT) begin + state <= READ_DONE; + rresp <= 2'b10; + end + else begin + count <= count + 1'b1; + end + end + + READ_DONE: begin + if (s_axi_rready) begin + state <= IDLE; + end + end + + WRITE_INIT: begin + if (s_axi_wvalid) begin + wr_data <= s_axi_wdata[RP_DWIDTH-1:0]; + state <= WRITE_IN_PROGRESS; + count <= 10'd0; + bresp <= 2'b00; + end + end + + WRITE_IN_PROGRESS: begin + if (reg_port_out_ready) begin + state <= WRITE_DONE; + end + else if (count >= TIMEOUT) begin + state <= READ_DONE; + bresp <= 2'b10; + end + else begin + count <= count + 1'b1; + end + end + + WRITE_DONE: begin + if (s_axi_bready) + state <= IDLE; + end + + default: begin + state <= IDLE; + end + + endcase + end + + assign s_axi_awready = (state == IDLE); + assign s_axi_wready = (state == WRITE_INIT); + assign s_axi_bvalid = (state == WRITE_DONE); + assign s_axi_bresp = bresp; + + assign s_axi_arready = (state == IDLE); + assign s_axi_rdata = rb_data; + assign s_axi_rvalid = (state == READ_DONE); + assign s_axi_rresp = rresp; + + assign reg_port_in_wt = (state == WRITE_INIT) & s_axi_wvalid; + assign reg_port_in_data = (state == WRITE_INIT) ? s_axi_wdata : wr_data; + assign reg_port_in_addr = addr; + + assign reg_port_in_rd = (state == READ_INIT); + +endmodule |