1//
2// Copyright 2016 Ettus Research
3// Copyright 2018 Ettus Research, a National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7// AXI4lite to NI Register Port interface
8//
9
10module axil_to_ni_regport #(
11  parameter RP_AWIDTH = 16,
12  parameter RP_DWIDTH = 32,
13  parameter TIMEOUT   = 512
14)(
15  input                  s_axi_aclk,
16  input                  s_axi_areset,
17
18  // AXI4lite interface
19  input [31:0]           s_axi_awaddr,
20  input                  s_axi_awvalid,
21  output                 s_axi_awready,
22  input [31:0]           s_axi_wdata,
23  input [3:0]            s_axi_wstrb,
24  input                  s_axi_wvalid,
25  output                 s_axi_wready,
26  output [1:0]           s_axi_bresp,
27  output                 s_axi_bvalid,
28  input                  s_axi_bready,
29  input [31:0]           s_axi_araddr,
30  input                  s_axi_arvalid,
31  output                 s_axi_arready,
32  output [31:0]          s_axi_rdata,
33  output [1:0]           s_axi_rresp,
34  output                 s_axi_rvalid,
35  input                  s_axi_rready,
36
37  // RegPort interface, the out vs in
38  // is seen from the slave device
39  // hooked up to the regport
40  output                 reg_port_in_rd,
41  output                 reg_port_in_wt,
42  output [RP_AWIDTH-1:0] reg_port_in_addr,
43  output [RP_DWIDTH-1:0] reg_port_in_data,
44  input  [RP_DWIDTH-1:0] reg_port_out_data,
45  input                  reg_port_out_ready
46);
47
48  localparam IDLE              = 3'd0;
49  localparam READ_INIT         = 3'd1;
50  localparam WRITE_INIT        = 3'd2;
51  localparam READ_IN_PROGRESS  = 3'd3;
52  localparam WRITE_IN_PROGRESS = 3'd4;
53  localparam WRITE_DONE        = 3'd5;
54  localparam READ_DONE         = 3'd6;
55
56  reg [RP_AWIDTH-1:0] addr;
57  reg [RP_DWIDTH-1:0] rb_data;
58  reg [RP_DWIDTH-1:0] wr_data;
59  reg [2:0] state;
60  reg [9:0] count;
61  reg [1:0] rresp;
62  reg [1:0] bresp;
63
64  always @ (posedge s_axi_aclk) begin
65    if (s_axi_areset) begin
66      state   <= IDLE;
67      addr    <= 'd0;
68      rb_data <= 'd0;
69      wr_data <= 'd0;
70
71      count    <= 10'd0;
72      rresp    <= 2'd0;
73      bresp    <= 2'd0;
74    end
75    else case (state)
76
77    IDLE: begin
78      if (s_axi_arvalid) begin
79        state <= READ_INIT;
80        addr  <= s_axi_araddr[RP_AWIDTH-1:0];
81      end
82      else if (s_axi_awvalid) begin
83        state <= WRITE_INIT;
84        addr  <= s_axi_awaddr[RP_AWIDTH-1:0];
85      end
86    end
87
88    READ_INIT: begin
89      state <= READ_IN_PROGRESS;
90      count <= 10'd0;
91      rresp <= 2'b00;
92    end
93
94    READ_IN_PROGRESS: begin
95      if (reg_port_out_ready) begin
96        rb_data <= reg_port_out_data;
97        state   <= READ_DONE;
98      end
99      else if (count >= TIMEOUT) begin
100        state   <= READ_DONE;
101        rresp   <= 2'b10;
102      end
103      else begin
104        count   <= count + 1'b1;
105      end
106    end
107
108    READ_DONE: begin
109      if (s_axi_rready) begin
110        state <= IDLE;
111      end
112    end
113
114    WRITE_INIT: begin
115      if (s_axi_wvalid) begin
116        wr_data <= s_axi_wdata[RP_DWIDTH-1:0];
117        state   <= WRITE_IN_PROGRESS;
118        count <= 10'd0;
119        bresp <= 2'b00;
120      end
121    end
122
123    WRITE_IN_PROGRESS: begin
124      if (reg_port_out_ready) begin
125        state <= WRITE_DONE;
126      end
127      else if (count >= TIMEOUT) begin
128        state   <= READ_DONE;
129        bresp   <= 2'b10;
130      end
131      else begin
132        count   <= count + 1'b1;
133      end
134    end
135
136    WRITE_DONE: begin
137      if (s_axi_bready)
138        state <= IDLE;
139    end
140
141    default: begin
142      state <= IDLE;
143    end
144
145    endcase
146  end
147
148  assign s_axi_awready = (state == IDLE);
149  assign s_axi_wready  = (state == WRITE_INIT);
150  assign s_axi_bvalid  = (state == WRITE_DONE);
151  assign s_axi_bresp   = bresp;
152
153  assign s_axi_arready = (state == IDLE);
154  assign s_axi_rdata   = rb_data;
155  assign s_axi_rvalid  = (state == READ_DONE);
156  assign s_axi_rresp   = rresp;
157
158  assign reg_port_in_wt   = (state == WRITE_INIT) & s_axi_wvalid;
159  assign reg_port_in_data = (state == WRITE_INIT) ? s_axi_wdata : wr_data;
160  assign reg_port_in_addr = addr;
161
162  assign reg_port_in_rd   = (state == READ_INIT);
163
164endmodule
165