1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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
|