-
Notifications
You must be signed in to change notification settings - Fork 2
/
rggen_adapter_common.sv
210 lines (183 loc) · 6.57 KB
/
rggen_adapter_common.sv
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
module rggen_adapter_common
import rggen_rtl_pkg::*;
#(
parameter int ADDRESS_WIDTH = 8,
parameter int LOCAL_ADDRESS_WIDTH = 8,
parameter int BUS_WIDTH = 32,
parameter int STROBE_WIDTH = BUS_WIDTH / 8,
parameter int REGISTERS = 1,
parameter bit PRE_DECODE = 0,
parameter bit [ADDRESS_WIDTH-1:0] BASE_ADDRESS = '0,
parameter int BYTE_SIZE = 256,
parameter bit ERROR_STATUS = 0,
parameter bit [BUS_WIDTH-1:0] DEFAULT_READ_DATA = '0,
parameter bit INSERT_SLICER = 0
)(
input logic i_clk,
input logic i_rst_n,
rggen_bus_if.slave bus_if,
rggen_register_if.host register_if[REGISTERS]
);
genvar i;
// State
logic busy;
always_ff @(posedge i_clk, negedge i_rst_n) begin
if (!i_rst_n) begin
busy <= '0;
end
else if (bus_if.ready) begin
busy <= '0;
end
else if (bus_if.valid) begin
busy <= '1;
end
end
// Pre-decode
logic inside_range;
assign inside_range = pre_decode(bus_if.address);
function automatic logic pre_decode(
logic [ADDRESS_WIDTH-1:0] address
);
if (PRE_DECODE) begin
logic [ADDRESS_WIDTH-1:0] begin_addrss;
logic [ADDRESS_WIDTH-1:0] end_address;
begin_addrss = BASE_ADDRESS;
end_address = BASE_ADDRESS + ADDRESS_WIDTH'(BYTE_SIZE - 1);
return (address >= begin_addrss) && (address <= end_address);
end
else begin
return '1;
end
endfunction
// Request
logic bus_valid;
rggen_access bus_access;
logic [LOCAL_ADDRESS_WIDTH-1:0] bus_address;
logic [BUS_WIDTH-1:0] bus_write_data;
logic [STROBE_WIDTH-1:0] bus_strobe;
generate
if (INSERT_SLICER) begin : g_request_slicer
always_ff @(posedge i_clk, negedge i_rst_n) begin
if (!i_rst_n) begin
bus_valid <= '0;
end
else if (!busy) begin
bus_valid <= bus_if.valid && inside_range;
end
else begin
bus_valid <= '0;
end
end
always_ff @(posedge i_clk, negedge i_rst_n) begin
if (!i_rst_n) begin
bus_access <= rggen_access'(0);
bus_address <= '0;
bus_write_data <= '0;
bus_strobe <= '0;
end
else if (bus_if.valid && (!busy)) begin
bus_access <= bus_if.access;
bus_address <= get_local_address(bus_if.address);
bus_write_data <= bus_if.write_data;
bus_strobe <= bus_if.strobe;
end
end
end
else begin : g_no_request_slicer
assign bus_valid = bus_if.valid && inside_range && (!busy);
assign bus_access = bus_if.access;
assign bus_address = get_local_address(bus_if.address);
assign bus_write_data = bus_if.write_data;
assign bus_strobe = bus_if.strobe;
end
for (i = 0;i < REGISTERS;++i) begin : g_request
assign register_if[i].valid = bus_valid;
assign register_if[i].access = bus_access;
assign register_if[i].address = bus_address;
assign register_if[i].write_data = bus_write_data;
assign register_if[i].strobe = get_regiser_strobe(bus_strobe);
end
endgenerate
function automatic logic [LOCAL_ADDRESS_WIDTH-1:0] get_local_address(
logic [ADDRESS_WIDTH-1:0] address
);
logic [ADDRESS_WIDTH-1:0] local_address;
if (BASE_ADDRESS[0+:LOCAL_ADDRESS_WIDTH] == '0) begin
local_address = address;
end
else begin
local_address = address - BASE_ADDRESS;
end
return local_address[0+:LOCAL_ADDRESS_WIDTH];
endfunction
function automatic logic [BUS_WIDTH-1:0] get_regiser_strobe(
logic [STROBE_WIDTH-1:0] bus_strobe
);
logic [BUS_WIDTH-1:0] strobe;
if (STROBE_WIDTH == BUS_WIDTH) begin
strobe = BUS_WIDTH'(bus_strobe);
end
else begin
for (int i = 0;i < STROBE_WIDTH;++i) begin
strobe[8*i+:8] = {8{bus_strobe[i]}};
end
end
return strobe;
endfunction
// Response
localparam rggen_status DEFAULT_STATUS = (ERROR_STATUS) ? RGGEN_SLAVE_ERROR : RGGEN_OKAY;
localparam int STATUS_WIDTH = $bits(rggen_status);
localparam int RESPONSE_WIDTH = BUS_WIDTH + STATUS_WIDTH;
logic [REGISTERS-1:0] ready;
logic [REGISTERS-1:0] active;
logic [REGISTERS-1:0][RESPONSE_WIDTH-1:0] response;
logic [RESPONSE_WIDTH-1:0] selected_response;
logic register_inactive;
rggen_status register_status;
logic [BUS_WIDTH-1:0] register_read_data;
generate
for (i = 0;i < REGISTERS;++i) begin : g_response
assign active[i] = register_if[i].active;
assign ready[i] = register_if[i].ready;
assign response[i] = {register_if[i].status, register_if[i].read_data};
end
endgenerate
rggen_mux #(
.WIDTH (RESPONSE_WIDTH ),
.ENTRIES (REGISTERS )
) u_mux (
.i_select (active ),
.i_data (response ),
.o_data (selected_response )
);
assign register_inactive = (!inside_range) || (active == '0);
assign register_status = rggen_status'(selected_response[BUS_WIDTH+:STATUS_WIDTH]);
assign register_read_data = selected_response[0+:BUS_WIDTH];
assign bus_if.ready = ((!INSERT_SLICER) || busy) && ((ready != '0) || register_inactive);
assign bus_if.status = (register_inactive) ? DEFAULT_STATUS : register_status;
assign bus_if.read_data = (register_inactive) ? DEFAULT_READ_DATA : register_read_data;
`ifdef RGGEN_ENABLE_SVA
ast_hold_request_command_until_ready_is_high:
assert property (
@(posedge i_clk)
(bus_if.valid && (!bus_if.ready)) |=>
($stable(bus_if.valid) && $stable(bus_if.access) && $stable(bus_if.address))
);
ast_hold_request_data_until_ready_is_high:
assert property (
@(posedge i_clk)
(bus_if.valid && (!bus_if.ready) && (bus_if.access != RGGEN_READ)) |=>
($stable(bus_if.write_data) && $stable(bus_if.strobe))
);
ast_only_one_register_is_active:
assert property (
@(posedge i_clk)
(bus_if.valid && (active != '0)) |-> $onehot(active)
);
ast_assert_ready_of_active_register_only:
assert property (
@(posedge i_clk)
(bus_if.valid && (ready != '0)) |-> (active == ready)
);
`endif
endmodule