-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathoscilloscope.v
285 lines (236 loc) · 7.39 KB
/
oscilloscope.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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*
This module takes a 8 bit compressor input and outputs a signal to the VGA block
depending on the trigger from the trigger block.
Horizontal time base is adjusted by downsampling the input
based on user selected settings.
Authors: Zubair Lutfullah and M. Bakir
*/
module oscilloscope(
//INPUTS
input clk_25, //25MHz clock
input clk_62_5, //62.5 MHz clock
input rst_n, //Reset Negative
input [7:0]in_y, //Channel 1 from compressor
input [7:0]in_y2, //Channel 2 from compressor
input trigger, //Channel 1 trigger
input trigger_second, //Channel 2 trigger
input [2:0]downsample_sel, //Channel 1 Time-base downsample sel
input [2:0]downsample_sel_second, //Channel 2 Time-base downsample sel
//OUTPUTS
output reg [7:0]out_x, //Horizontal pixel location output for VGA block
output reg [7:0]out_y, //Vertical pixel location output for VGA block
output reg write_en, //Write Enable for VGA block.
output reg [11:0]RGB); //Color of pixel
//State machine variables
parameter CLEAN = 2'b00;
parameter FILL = 2'b01;
parameter DISPLAY = 2'b10;
parameter END = 2'b11;
reg [1:0]state;
//Temporary Registers
reg [7:0]read_addr; //Read Address for reading from RAM
reg [7:0]write_addr; //Write Address for writing to RAM
reg buffer_full; //flag if buffer has been filled by ADC.
reg display_clean; //flag if vga screen has been cleared.
// Declare the RAM variable
reg [7:0] ram_y[159:0]; //Channel 1 buffer
reg [7:0] ram_y2[159:0]; //Channel 2 buffer
reg second_channel; //flag for which channel is being processed
//Horizontal time base downsample registers
reg [2:0]downsample_counter; //Counter for downsampling channel 1
reg [2:0]downsample_counter_second; //Counter for downsampling channel 2
//Clock domain 62.5 MHz
always @ (posedge clk_62_5)
begin
if(!rst_n) //Clear registers on reset
begin
write_addr <= 0;
buffer_full <= 0;
downsample_counter <=0;
downsample_counter_second <=0;
end //end if rst
else
begin
case(state) //State machine
CLEAN : begin
//Nothing in this clock domain
end
FILL : begin
//Fill buffer from ADC samples based on downsample counter.
//If buffer full. Raise flag for other clock domain.
if(write_addr == 8'b10011111)
begin
buffer_full <= 1;
//state <= DISPLAY;
end//end if writeadd == 8'b111111
else
begin
if(second_channel)
begin
if(downsample_counter_second == 0)
begin
if(in_y[7])
ram_y[write_addr] <= 8'b10000000;
else
ram_y[write_addr] <= in_y;
write_addr <= write_addr + 1;
end
end
else
begin
if(downsample_counter == 0)
begin
if(in_y2[7])
ram_y2[write_addr] <= 8'b10000000;
else
ram_y2[write_addr] <= in_y2;
write_addr <= write_addr + 1;
end
end
end//end else
end //end fill case
DISPLAY: begin
//Nothing in this clock domain
end
END: begin
//Clear temporary registers for next cycle.
write_addr <= 0;
buffer_full <= 0;
downsample_counter <= 0;
downsample_counter_second <= 0;
end
default: begin
write_addr <= 0;
buffer_full <= 0;
downsample_counter <= 0;
downsample_counter_second <= 0;
end //end default case
endcase //endcase state
//Downsample for horizontal time base adjustment
if(downsample_counter == downsample_sel)
downsample_counter <= 0; //Reset counter based on user input
else
downsample_counter <= downsample_counter + 1;
if(downsample_counter_second == downsample_sel_second)
downsample_counter_second <= 0; //Reset counter based on user input
else
downsample_counter_second <= downsample_counter_second + 1;
end//end begin of else of if(rst_n)
end //end always @ posedge clk 65MHz
//Second clock domain. 25MHz.
always @ (posedge clk_25)
begin
if(!rst_n)
begin
//Clear registers on reset
display_clean <=0;
read_addr <= 0;
write_en <= 0;
read_addr <= 0;
write_en <= 0;
out_y <= 0;
out_x <= 0;
end//end if rst_n
else
begin
case (state) //State machine
CLEAN : begin
//Read buffer again. Clear those pixels by
//replacing with black for background
//or white if grid location.
//Once cleaned. Next state is FILL to refill buffer.
if(read_addr == 8'b10011111)
begin
display_clean <= 1;
state <= FILL;
end //end (if(read_addr == 8'b111111))
else
begin
if(second_channel)
begin
out_y <= ram_y[read_addr];
end
else
begin
out_y <= ram_y2[read_addr];
end
read_addr <= read_addr + 1;
out_x <= read_addr;
write_en <= 1;
if(read_addr == 0 || read_addr == 20 || read_addr == 40 || read_addr == 60 || read_addr == 80 || read_addr == 100 || read_addr == 120
|| read_addr == 140 || read_addr == 160 || out_y == 0 || out_y == 19 || out_y == 39 || out_y == 59 || out_y == 79
|| out_y == 99 || out_y == 119)
RGB <= 12'b111111111111;
else
RGB <= 12'b000000000000;
end
end //end CLEAN case
FILL : begin
//Clear temporary registers.
//Wait for buffer flag to go high
//by the other clock domain.
read_addr <= 0;
write_en <= 0;
read_addr <= 0;
write_en <= 0;
out_y <= 0;
out_x <= 0;
if(buffer_full)
state <= DISPLAY;
else
state <= FILL;
end //end FILL case
DISPLAY : begin
//Read buffer. Output to VGA block to display_clean
if(read_addr == 8'b10011110)
begin
state <= END;
end //end (if(read_addr == 8'b111111))
else
begin
if(second_channel)
begin
out_y <= ram_y[read_addr];
RGB <= 12'b000000111111;
end
else
begin
out_y <= ram_y2[read_addr];
RGB <= 12'b111111000000;
end //end if second_channel
read_addr <= read_addr + 1;
out_x <= read_addr;
write_en <= 1;
end //end else
end //end DISPLAY case
END: begin
//Clear temporary registers
//Wait for trigger flag to go high
//signaling another loop for the state machine.
read_addr <= 0;
write_en <= 0;
out_y <= 0;
out_x <= 0;
if(trigger == 1)
begin
state <= CLEAN;
second_channel <= 1;
end
else if(trigger_second == 1)
begin
state <= CLEAN;
second_channel <= 0;
end
else
state <= END;
end //end END case
default: begin
read_addr <= 0;
write_en <= 0;
out_y <= 0;
out_x <= 0;
end
endcase
end //end else of if rst
end //end always @ posedge clk 65MHz
endmodule