📄 trace_w_pipe.v
字号:
// Copyright (c) Charles HY Cheung, Cornell University
//Draws a trace at the specified coordinates
// MAX 256x1024 drawing area real-time
// Pipeline mode
module TRACE(
input pipeline, //mode of the trace
input CLOCK_60,
//VGA
input VGA_CTRL_CLK,
input VGA_VS,
input VGA_HS,
input [9:0] Coord_X,
input [9:0] Coord_Y,
input reset,
input stop, //stops trace
input cont_line, //continue after end of trace
input [19:0] acq_rate, //max 1MHz/1MHz
input [20:0] volperdivval, //inverse volts per div modifier
input [20:0] secperdivctr, //secs per div counter
input [9:0] offsetpix, //offset pixels
//trc draw area
input [3:0] xdivs,
input [3:0] ydivs,
input [9:0] xmin,
input [9:0] xmax,
input [9:0] ymin,
input [9:0] ymax,
input [7:0] color_bkg,
input [7:0] color_grid,
input [7:0] color_trace,
input [7:0] color_scrn,
//osc interface
input osc_clk,
input [15:0] osc_raw,
input osc_full,
output reg osc_hold,
output reg osc_clk_e,
output reg [15:0] osc_max_samps,
//input [15:0] osc_out,
//SRAM
output reg [15:0] data_reg,
output reg [17:0] addr_reg,
output reg we,
//to osc acquisition clk
output reg acq_clk,
//RAM
input [15:0] acq_data,
input [15:0] acq_secperdiv,
output reg [15:0] acq_data_addr,
output reg ram_sw,
output reg ram_wren
);
reg [9:0] x0_reg, x1_reg, y0_reg, y1_reg; //grid generation bounds for pipeline
//generates a GRID for graphics display, max 10 divs
wire [9:0] x0 = (pipeline) ? x0_reg : xmin;
wire [9:0] x1 = (pipeline) ? x1_reg : xmax;
wire [9:0] y0 = (pipeline) ? y0_reg : ymin;
wire [9:0] y1 = (pipeline) ? y1_reg : ymax;
//set the resolution from bounds
wire [9:0] resx = x1 - x0;
wire [9:0] resy = y1 - y0;
//set the number of pixels per div
wire [9:0] xpxperdiv = resx / ((xdivs>10)?10:xdivs);
wire [9:0] ypxperdiv = resy / ((ydivs>10)?10:ydivs);
//maximum 9 divs lines (10divs) set individually
wire [9:0] xdiv1 = xpxperdiv;
wire [9:0] xdiv2 = (xpxperdiv*2 <= resx)? xpxperdiv*2 : resx;
wire [9:0] xdiv3 = (xpxperdiv*3 <= resx)? xpxperdiv*3 : resx;
wire [9:0] xdiv4 = (xpxperdiv*4 <= resx)? xpxperdiv*4 : resx;
wire [9:0] xdiv5 = (xpxperdiv*5 <= resx)? xpxperdiv*5 : resx;
wire [9:0] xdiv6 = (xpxperdiv*6 <= resx)? xpxperdiv*6 : resx;
wire [9:0] xdiv7 = (xpxperdiv*7 <= resx)? xpxperdiv*7 : resx;
wire [9:0] xdiv8 = (xpxperdiv*8 <= resx)? xpxperdiv*8 : resx;
wire [9:0] xdiv9 = (xpxperdiv*9 <= resx)? xpxperdiv*9 : resx;
wire [9:0] ydiv1 = ypxperdiv;
wire [9:0] ydiv2 = (ypxperdiv*2 <= resy)? ypxperdiv*2 : resy;
wire [9:0] ydiv3 = (ypxperdiv*3 <= resy)? ypxperdiv*3 : resy;
wire [9:0] ydiv4 = (ypxperdiv*4 <= resy)? ypxperdiv*4 : resy;
wire [9:0] ydiv5 = (ypxperdiv*5 <= resy)? ypxperdiv*5 : resy;
wire [9:0] ydiv6 = (ypxperdiv*6 <= resy)? ypxperdiv*6 : resy;
wire [9:0] ydiv7 = (ypxperdiv*7 <= resy)? ypxperdiv*7 : resy;
wire [9:0] ydiv8 = (ypxperdiv*8 <= resy)? ypxperdiv*8 : resy;
wire [9:0] ydiv9 = (ypxperdiv*9 <= resy)? ypxperdiv*9 : resy;
//true if within bounds
wire boxed=(
(rw_x>=x0) && (rw_x<=x1) &&
(rw_y>=y0) && (rw_y<=y1)
)?1:0;
//true if on the gridlines
wire ongrid = (rw_y==y0 || rw_y==y1 ||
rw_x==x0 || rw_x==x1 ||
rw_x==xdiv1+x0 ||
rw_x==xdiv2+x0 ||
rw_x==xdiv3+x0 ||
rw_x==xdiv4+x0 ||
rw_x==xdiv5+x0 ||
rw_x==xdiv6+x0 ||
rw_x==xdiv7+x0 ||
rw_x==xdiv8+x0 ||
rw_x==xdiv9+x0 ||
rw_y==ydiv1+y0 ||
rw_y==ydiv2+y0 ||
rw_y==ydiv3+y0 ||
rw_y==ydiv4+y0 ||
rw_y==ydiv5+y0 ||
rw_y==ydiv6+y0 ||
rw_y==ydiv7+y0 ||
rw_y==ydiv8+y0 ||
rw_y==ydiv9+y0 )?1:0;
//internal registers
reg trc_init;
reg pipe_init;
reg pipe_init_start;
reg [3:0] state;
reg [3:0] jumpstate;
reg [9:0] rw_x; //
reg [9:0] rw_y; //temp read/write location
reg [9:0] cursor_x, cursor_y; //writing-cursor location
reg [20:0] count_buffer; //buffer to count to secperdivctr
reg [19:0] count_osc; //max disp_rate divider 1MHz/1MHz (1Hz)
reg trc_clk; //speed of trace write
reg [20:0] wait_count; //counter for screen redraw in HSVS (512)
reg [15:0] addr_trace; //trace location in y px
reg [15:0] acq_addr_inc; //increment for pipeline top trace
wire [9:0] offset = (offsetpix<=resy) ? offsetpix : resy ; //large offset handling
wire trace_write = (((osc_raw*resy)/32'd65536)>y1)?0:(
(trace_pos > y1 || trace_pos < y0) ? 0:1); //if overshoot, do not write trace
wire [15:0] trace_pos = y1-(osc_raw*resy)/(32'd65536+volperdivval)+offset; //resized position of trace
//states
parameter loop1=4'd1, update=4'd2, wait_key=4'd3,
init1=4'd4, loop2=4'd5, buffer2=4'd6, buffer3=4'd7, loop2a=4'd8,
loop1a=4'd9, loop2b=4'd10, loop1b=4'd11, loop2c=4'd12, update_top=4'd13;
//generate trace display clock
always@(posedge VGA_CTRL_CLK)
begin
if (reset) begin count_buffer <= 0; trc_clk <= 1; end
else if (~VGA_VS | ~VGA_HS)
begin
trc_clk <= (count_buffer == secperdivctr) ? 1 : 0;
count_buffer <= (count_buffer == secperdivctr) ? 0 : count_buffer + 1;
end
end
//generate sampling clock from osc
always@(posedge osc_clk or posedge reset)
begin
if (reset)
begin
count_osc <= 0;
acq_clk <= 1;
end
else
begin
acq_clk <= (count_osc == acq_rate) ? 1 : 0;
count_osc <= (count_osc == acq_rate) ? 0 : count_osc + 1;
end
end
wire ram_write = (((acq_data*resy)/32'd65536)>y1)?0:(
(ram_pos > y1 || ram_pos < y0) ? 0:1); //if overshoot, do not write trace
wire [15:0] ram_pos = y1-(acq_data*resy)/(32'd65536+volperdivval);
always@(posedge VGA_CTRL_CLK)
begin
if (reset)
begin
//init ram
ram_sw <= 0;
ram_wren <= 0;
acq_data_addr <= 0;
osc_hold <= 1;
//init pipe draw window
x0_reg = 10;
x1_reg = 630;
y0_reg = 250;
y1_reg = 470;
//clr screen
rw_x = Coord_X; rw_y = Coord_Y;
addr_reg <= {rw_x[9:1],rw_y[8:0]} ; // [17:0]
we <= boxed ? 1'b1 : 1'b0; //write some memory
if (rw_x[0]) data_reg[15:8] <= color_scrn;
else data_reg[7:0] <= color_scrn;
cursor_x <= x0; //write-cursor x at first column
wait_count <= 0;
jumpstate <= init1;
if (~pipeline)
begin
pipe_init <= 0;
trc_init <= 1;
end
else
begin
pipe_init <= 1;
pipe_init_start <=1;
trc_init <= 0;
end
end
else if (trc_init & ~stop)
begin
rw_x = Coord_X; rw_y = Coord_Y;
// write grid
addr_reg <= {rw_x[9:1],rw_y[8:0]} ; // [17:0]
we <= boxed ? 1'b0 : 1'b1; //write some memory in box
if (rw_x[0]) data_reg[15:8] <= (ongrid? color_grid : color_bkg);
else data_reg[7:0] <= (ongrid? color_grid : color_bkg);
if (boxed) wait_count <= wait_count + 1;
if (wait_count == (resx+1)*(resy+1) )
begin
trc_init <= 0;
wait_count <= 0;
osc_clk_e <= 1;
state <= jumpstate;
end
end
//intialize pipeline
else if (pipe_init & ~stop)
begin
if (pipe_init_start == 1)
begin
//set adddr scan rate for top trace
acq_addr_inc <= 65536/resx;
//set osc to sample & hold
osc_clk_e <= 1;
osc_max_samps <= 16'hFFFF;
osc_hold <= 0;
//set
end
else if (osc_full) //done sampling
begin
ram_sw <= 1; //set ram in read mode (ram_wren is 0)
trc_init <= 1;
pipe_init <= 0;
end
pipe_init_start <= 0; //started indicator
end
//modify display during sync
else if ((~VGA_VS | ~VGA_HS) & ~stop & ~pipeline & trc_clk) //sync is active low
begin
case(state)
init1: //init
begin
we <= 1'b1; //no mem write
state <= loop1;
end
loop1:
begin
rw_x = cursor_x; rw_y = {1'd0, trace_pos[8:0]}; //update from trace
we <= trace_write ? 1'b0 : 1'b1; //mem write depends bounded trace
addr_reg <= {rw_x[9:1], rw_y[8:0]}; //write location
if (rw_x[0]) data_reg[15:8] <= color_trace;
else data_reg[7:0] <= color_trace;
state <= update;
end
//Writing-Cursor location update
//End-Of-Line checking
update:
begin
we <= 1'b1; //no mem write
if (cursor_x < x1) // EOL not reached
begin
cursor_x <= cursor_x + 10'd1; //increment x cursor
end
else
begin // EOL reached
cursor_x <= x0; //write-cursor x at first column
end
state <= wait_key; //restart testing
end
wait_key: //wait for pushbutton before refreshing
begin
if (cursor_x == x1)
begin
if (cont_line) trc_init <= 1;
end
else state <= loop1;
end
endcase
end
else if ((~VGA_VS | ~VGA_HS) & ~stop & pipeline & trc_clk) //sync is active low
begin
case (state)
init1: //init
begin
we <= 1'b1; //no mem write
rw_x = cursor_x; rw_y = {1'd0, ram_pos[8:0]-240};
we <= ram_write ? 1'b0 : 1'b1;
addr_reg <= {rw_x[9:1], rw_y[8:0]}; //write location
if (rw_x[0]) data_reg[15:8] <= color_trace;
else data_reg[7:0] <= color_trace;
state <= update_top;
end
//Writing-Cursor location update
//End-Of-Line checking
update_top:
begin
we <= 1'b1; //no mem write
if (cursor_x < x1) // EOL not reached
begin
cursor_x <= cursor_x + 10'd1; //increment x cursor
acq_data_addr <= acq_data_addr + acq_addr_inc;
state <= init1; //continue trace
end
else
begin // EOL reached
cursor_x <= x0;//write-cursor x at first column
acq_data_addr <= 0; //reset addr
state <= loop1; //trace bottom
end
end
loop1:
begin
we <= 1'b1; //no mem write
rw_x = cursor_x; rw_y = {1'd0, ram_pos[8:0]}; //update from trace
we <= trace_write ? 1'b0 : 1'b1;
addr_reg <= {rw_x[9:1], rw_y[8:0]}; //write location
if (rw_x[0]) data_reg[15:8] <= color_trace;
else data_reg[7:0] <= color_trace;
state <= update;
end
//Writing-Cursor location update
//End-Of-Line checking
update:
begin
we <= 1'b1; //no mem write
if (cursor_x < x1) // EOL not reached
begin
cursor_x <= cursor_x + 10'd1; //increment x cursor
acq_data_addr <= acq_data_addr + acq_secperdiv;
end
else
begin // EOL reached
cursor_x <= x0; //write-cursor x at first column
end
state <= wait_key; //restart testing
end
wait_key: //wait for pushbutton before refreshing
begin
if (cursor_x == x1)
begin
if (cont_line)
begin
trc_init <= 1;
jumpstate <= loop1;
end
end
else state <= loop1;
end
endcase
end
//show display when not blanking,
//which implies we=1 (not enabled); and use VGA module address
else
begin
we <= 1'b1;
addr_reg <= {Coord_X[9:1],Coord_Y[8:0]} ;
end
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -