-
Notifications
You must be signed in to change notification settings - Fork 398
/
Copy pathlatency_aware_read_master.v
247 lines (208 loc) · 6.49 KB
/
latency_aware_read_master.v
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
Legal Notice: (C)2007 Altera Corporation. All rights reserved. Your
use of Altera Corporation's design tools, logic functions and other
software and tools, and its AMPP partner logic functions, and any
output files any of the foregoing (including device programming or
simulation files), and any associated documentation or information are
expressly subject to the terms and conditions of the Altera Program
License Subscription Agreement or other applicable license agreement,
including, without limitation, that your use is for the sole purpose
of programming logic devices manufactured by Altera and sold by Altera
or its authorized distributors. Please refer to the applicable
agreement for further details.
*/
/*
Author: JCJB
Date: 11/04/2007
This latency aware read master is passed a word aligned address, length in bytes,
and a 'go' bit. The master will continue to post reads until the length register
reaches a value of zero. When all the reads return the done bit will be asserted.
To use this master you must simply drive the control signals into this block,
and also read the data from the exposed read FIFO. To read from the exposed FIFO
use the 'user_read_buffer' signal to pop data from the FIFO 'user_buffer_data'.
The signal 'user_data_available' is asserted whenever data is available from the
exposed FIFO.
*/
// altera message_off 10230
module latency_aware_read_master (
clk,
reset,
// control inputs and outputs
control_fixed_location,
control_read_base,
control_read_length,
control_go,
control_done,
control_early_done,
// user logic inputs and outputs
user_read_buffer,
user_buffer_data,
user_data_available,
// master inputs and outputs
master_address,
master_read,
master_byteenable,
master_readdata,
master_readdatavalid,
master_waitrequest
);
parameter DATAWIDTH = 32;
parameter BYTEENABLEWIDTH = 4;
parameter ADDRESSWIDTH = 32;
parameter FIFODEPTH = 32;
parameter FIFODEPTH_LOG2 = 5;
parameter FIFOUSEMEMORY = 1; // set to 0 to use LEs instead
input clk;
input reset;
// control inputs and outputs
input control_fixed_location;
input [ADDRESSWIDTH-1:0] control_read_base;
input [ADDRESSWIDTH-1:0] control_read_length;
input control_go;
output wire control_done;
output wire control_early_done; // don't use this unless you know what you are doing!
// user logic inputs and outputs
input user_read_buffer;
output wire [DATAWIDTH-1:0] user_buffer_data;
output wire user_data_available;
// master inputs and outputs
input master_waitrequest;
input master_readdatavalid;
input [DATAWIDTH-1:0] master_readdata;
output wire [ADDRESSWIDTH-1:0] master_address;
output wire master_read;
output wire [BYTEENABLEWIDTH-1:0] master_byteenable;
// internal control signals
reg control_fixed_location_d1;
wire fifo_empty;
reg [ADDRESSWIDTH-1:0] address;
reg [ADDRESSWIDTH-1:0] length;
reg [FIFODEPTH_LOG2-1:0] reads_pending;
wire increment_address;
wire too_many_pending_reads;
reg too_many_pending_reads_d1;
wire [FIFODEPTH_LOG2-1:0] fifo_used;
// registering the control_fixed_location bit
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
control_fixed_location_d1 <= 0;
end
else
begin
if (control_go == 1)
begin
control_fixed_location_d1 <= control_fixed_location;
end
end
end
// master address logic
assign master_address = address;
assign master_byteenable = -1; // all ones, always performing word size accesses
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
address <= 0;
end
else
begin
if(control_go == 1)
begin
address <= control_read_base;
end
else if((increment_address == 1) & (control_fixed_location_d1 == 0))
begin
address <= address + BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// master length logic
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
length <= 0;
end
else
begin
if(control_go == 1)
begin
length <= control_read_length;
end
else if(increment_address == 1)
begin
length <= length - BYTEENABLEWIDTH; // always performing word size accesses
end
end
end
// control logic
assign too_many_pending_reads = (fifo_used + reads_pending) >= (FIFODEPTH - 4);
assign master_read = (length != 0) & (too_many_pending_reads_d1 == 0);
assign increment_address = (length != 0) & (too_many_pending_reads_d1 == 0) & (master_waitrequest == 0);
assign control_done = (reads_pending == 0) & (length == 0); // master done posting reads and all reads have returned
assign control_early_done = (length == 0); // if you need all the pending reads to return then use 'control_done' instead of this signal
always @ (posedge clk)
begin
if (reset == 1)
begin
too_many_pending_reads_d1 <= 0;
end
else
begin
too_many_pending_reads_d1 <= too_many_pending_reads;
end
end
always @ (posedge clk or posedge reset)
begin
if (reset == 1)
begin
reads_pending <= 0;
end
else
begin
if(increment_address == 1)
begin
if(master_readdatavalid == 0)
begin
reads_pending <= reads_pending + 1;
end
else
begin
reads_pending <= reads_pending; // a read was posted, but another returned
end
end
else
begin
if(master_readdatavalid == 0)
begin
reads_pending <= reads_pending; // read was not posted and no read returned
end
else
begin
reads_pending <= reads_pending - 1; // read was not posted but a read returned
end
end
end
end
// read data feeding user logic
assign user_data_available = !fifo_empty;
scfifo the_master_to_user_fifo (
.aclr (reset),
.clock (clk),
.data (master_readdata),
.empty (fifo_empty),
.q (user_buffer_data),
.rdreq (user_read_buffer),
.usedw (fifo_used),
.wrreq (master_readdatavalid)
);
defparam the_master_to_user_fifo.lpm_width = DATAWIDTH;
defparam the_master_to_user_fifo.lpm_numwords = FIFODEPTH;
defparam the_master_to_user_fifo.lpm_showahead = "ON";
defparam the_master_to_user_fifo.use_eab = (FIFOUSEMEMORY == 1)? "ON" : "OFF";
defparam the_master_to_user_fifo.add_ram_output_register = "OFF";
defparam the_master_to_user_fifo.underflow_checking = "OFF";
defparam the_master_to_user_fifo.overflow_checking = "OFF";
endmodule