// // File: ntsc2zbt.v // Date: 27-Nov-05 // Author: I. Chuang // // Example for MIT 6.111 labkit showing how to prepare NTSC data // (from Javier's decoder) to be loaded into the ZBT RAM for video // display. // // The ZBT memory is 36 bits wide; we only use 32 bits of this, to // store 4 bytes of black-and-white intensity data from the NTSC // video input. ///////////////////////////////////////////////////////////////////////////// // Prepare data and address values to fill ZBT memory with NTSC data module ntsc_to_zbt(clk, vclk, fvh, dv, din, ntsc_addr, ntsc_data, ntsc_we, sw); input clk; // system clock input vclk; // video clock from camera input [2:0] fvh; input dv; input [7:0] din; output [18:0] ntsc_addr; output [35:0] ntsc_data; output ntsc_we; // write enable for NTSC data input sw; // switch which determines mode (for debugging) parameter COL_START = 10'd30; parameter ROW_START = 10'd30; // here put the luminance data from the ntsc decoder into the ram // this is for 1024 x 768 XGA display reg [9:0] col = 0; reg [9:0] row = 0; reg [7:0] vdata = 0; reg vwe; reg old_dv; reg old_frame; // frames are even / odd interlaced reg even_odd; // decode interlaced frame to this wire wire frame = fvh[2]; wire frame_edge = frame & ~old_frame; always @ (posedge vclk) //LLC1 is reference begin old_dv <= dv; vwe <= dv && !fvh[2] & ~old_dv; // if data valid, write it old_frame <= frame; even_odd = frame_edge ? ~even_odd : even_odd; if (!fvh[2]) begin col <= fvh[0] ? COL_START : (!fvh[2] && !fvh[1] && dv && (col < 1024)) ? col + 1 : col; row <= fvh[1] ? ROW_START : (!fvh[2] && fvh[0] && (row < 768)) ? row + 1 : row; vdata <= (dv && !fvh[2]) ? din : vdata; end end // synchronize with system clock reg [9:0] x[1:0],y[1:0]; reg [7:0] data[1:0]; reg we[1:0]; reg eo[1:0]; always @(posedge clk) begin {x[1],x[0]} <= {x[0],col}; {y[1],y[0]} <= {y[0],row}; {data[1],data[0]} <= {data[0],vdata}; {we[1],we[0]} <= {we[0],vwe}; {eo[1],eo[0]} <= {eo[0],even_odd}; end // edge detection on write enable signal reg old_we; wire we_edge = we[1] & ~old_we; always @(posedge clk) old_we <= we[1]; // shift each set of four bytes into a large register for the ZBT reg [31:0] mydata; always @(posedge clk) if (we_edge) mydata <= { mydata[23:0], data[1] }; // compute address to store data in wire [18:0] myaddr = {1'b0, y[1][8:0], eo[1], x[1][9:2]}; // alternate (256x192) image data and address wire [31:0] mydata2 = {data[1],data[1],data[1],data[1]}; wire [18:0] myaddr2 = {1'b0, y[1][8:0], eo[1], x[1][7:0]}; // update the output address and data only when four bytes ready reg [18:0] ntsc_addr; reg [35:0] ntsc_data; wire ntsc_we = sw ? we_edge : (we_edge & (x[1][1:0]==2'b00)); always @(posedge clk) if ( ntsc_we ) begin ntsc_addr <= sw ? myaddr2 : myaddr; // normal and expanded modes ntsc_data <= sw ? {4'b0,mydata2} : {4'b0,mydata}; end endmodule // ntsc_to_zbt