// // File: vga_graph2_buf.v // Date: 08-Nov-05 // Author: I. Chuang // // VGA display of a 638x256 graph (in a 640x258 window) // // This version buffers the input data, and copies it to the display // each time the input data buffer is filled, after the last display // of a full buffer is complete. // // This version also displays two different buffers (eg for the // real and imaginary results of a FFT). module vga_graph2_buf (reset,vclock,pix_clk,hcount,vcount,pixel, data1,data2,dclk,dstart,cx,cy); parameter NX = 640; // number of data pixels (horiz size) parameter GPIX_RGB1 = 3'b111; // pixel RGB for graph data1 parameter GPIX_RGB2 = 3'b100; // pixel RGB for graph data2 input reset; // system reset input vclock; // system synchronous clock input pix_clk; // video pixel clock input [9:0] hcount; // horizontal index of current pixel (0..639) input [9:0] vcount; // vertical index of current pixel (0..479) output [2:0] pixel; // char display's pixel input [9:0] cx; // x-location of graph (upper left corner) input [9:0] cy; // y-location of graph (upper left corner) input [7:0] data1; // next data word to clock in input [7:0] data2; // next data word to clock in input dclk; // data clock input dstart; // pulse to start data input // data is loaded begining with the clock cycle after (the single-cycle) // dstart signal rises. reg [7:0] gdat1[NX:0]; // ring buffer memory for display data1 reg [7:0] gdat2[NX:0]; // ring buffer memory for display data2 // pixels for the graph wire [9:0] hoff = hcount-cx; reg [9:0] hptr; always @(posedge vclock) hptr <= (hoff==0) ? 11'b0 // start display pointer at zero : ~pix_clk ? hptr : (hptr == NX-1 ? 0 : hptr+1); wire [9:0] voff = vcount - cy; wire [2:0] gpix = ( ((voff==gdat1[hptr]) ? GPIX_RGB1 : 3'b0) | ((voff==gdat2[hptr]) ? GPIX_RGB2 : 3'b0) ); // clocking in new data reg [7:0] vdat1[NX:0]; // ring buffer memory for incoming data1 reg [7:0] vdat2[NX:0]; // ring buffer memory for incoming data2 reg [10:0] buf_cnt; // counter on current size of new sample buf reg [10:0] cp_cnt; // count of samples copied to display buffer reg loading; reg [1:0] view_cycle; // number of vid frames after copy_done raised wire end_buf = (buf_cnt==NX); wire frame_over = (vcount == 478) & (hcount == 1) & pix_clk; wire copy_flag = loading & end_buf; // copy requested wire view_done = (view_cycle==2); // new data displayed wire copy_done = (cp_cnt == NX) ? 1 : 0; // copy done wire new_set = copy_done & view_done; // req new set of data // loop which makes sure a full video frame is displayed after // loaded data is copied to display buffer, before new sample is taken always @(posedge vclock) view_cycle <= (reset | ~copy_done) ? 0 : (copy_done & frame_over) ? view_cycle + 1 : view_cycle; // main loop which samples data and checks for load request always @(posedge vclock) if (reset) begin buf_cnt <= 0; loading <= 0; end else if (dclk) // dclk is the clock-enable data clock begin loading <= new_set ? 0 : dstart ? 1 // start one cycle after dstart rises : loading; buf_cnt <= new_set ? 0 : (loading & ~end_buf) ? buf_cnt + 1 : buf_cnt; if (loading) begin vdat1[buf_cnt] <= 8'd255 - data1; // store data vdat2[buf_cnt] <= 8'd255 - data2; // store data end end // copy from input buffer to display buffer when loaded & inbuf full always @(posedge vclock) begin // cp_cnt counts up to NX-1 and stays there until copy_flag -> 0 cp_cnt <= copy_flag ? ((cp_cnt < NX) ? cp_cnt + 1 : cp_cnt) : 0; gdat1[cp_cnt] <= copy_flag ? vdat1[cp_cnt] : gdat1[cp_cnt]; gdat2[cp_cnt] <= copy_flag ? vdat2[cp_cnt] : gdat2[cp_cnt]; end // border wire bpixfl = (hoff==0) | (hoff==NX) | (voff==0) | (voff==254); wire [2:0] bpix = bpixfl ? 3'b010 : 3'b0; // display flag wire dispflag = ( (hcount>=cx) & (hcount <= cx+NX) & (vcount >= cy-1) & (vcount <= (cy+10'd254)) ); // final pixel output reg [2:0] pixel; always @(posedge vclock) pixel <= pix_clk ? (dispflag ? gpix | bpix : 0) : pixel; endmodule // vga_graph