////////////////////////////////////////////////////////// //CS150 Fall 2002 //Check Point 2 Solution // //Warning: //All copies of the code or subsections of the code in this file //which were not contained in the original skeleton file for use //in CS150 class must contain this header. ////////////////////////////////////////////////////////// module Videomodule( p, sclk, sda, pal_ntsc, reset, // asserted low hsync, vsync, blank, screset, clock, rst_pin // asserted low ); output [9:0] p; output sclk,sda,pal_ntsc,reset,hsync,vsync,blank,screset; input clock,rst_pin; wire [7:0] v_data; wire [10:0] v_addr; wire rst,clk; reg [10:0] counter; reg [1:0] ns; reg [1:0] cs; reg [4:0] num_bits; wire rst_count,rst_line_count; wire [7:0] EAV,SAV; reg [9:0] line_counter; parameter initialState=2'b00; parameter sendingI2C = 2'b01; parameter resetCounter = 2'b10; parameter sendingVideo = 2'b11; assign rst = ~rst_pin; assign pal_ntsc = 1'b0; assign hsync = 1'b1; assign vsync = 1'b1; assign blank = 1'b1; assign reset = rst_pin; assign clk = clock; assign screset = 1'b0; // Shift register to store the I2C data ShiftRegister sda_data(.D(29'h05401180),.Q(shift_out),.clk(clock),.rst(rst), .shift(sda_shift)); // Clock only functions in the sendingI2C state assign sclk = (cs==sendingI2C) ? counter[5] : 1'b1; // Tells the shift register when to shift out a new bit assign sda_shift = (cs==sendingI2C) ? ~|counter[3:0]&counter[4]&&~counter[5] : 1'b0; // The sda output from the shift register assign sda = (cs==sendingI2C) ? shift_out : (cs==initialState && counter) ? ~counter[6] : 1'b1; // Reset signals for the counters assign rst_count = (cs==resetCounter); assign rst_line_count = (cs==resetCounter); // random bit assign EAV[7] = 1'b1; // F bit assign EAV[6] = (line_counter<10'd266 && line_counter>10'd3) ? 1'b0: 1'b1; // V bit assign EAV[5] = (line_counter<10'd20 || (line_counter>10'd263 && line_counter<10'd283)) ? 1'b1 : 1'b0; assign EAV[4] = 1'b1; assign EAV[3] = EAV[5] ^ EAV[4]; assign EAV[2] = EAV[6] ^ EAV[4]; assign EAV[1] = EAV[6] ^ EAV[5]; assign EAV[0] = EAV[4] ^ EAV[6] ^ EAV[5]; assign SAV[7] = 1'b1; assign SAV[6] = EAV[6]; assign SAV[5] = EAV[5]; assign SAV[4] = 1'b0; assign SAV[3] = SAV[5] ^ SAV[4]; assign SAV[2] = SAV[6] ^ SAV[4]; assign SAV[1] = SAV[6] ^ SAV[5]; assign SAV[0] = SAV[4] ^ SAV[6] ^ SAV[5]; // Determines what to output on p. Depending on the count, it's // either an EAV,SAV or actual video data. assign p[9:2] = (counter==11'd0 || counter==11'd270) ? 8'hFF : (counter==11'd1 || counter==11'd2 || counter==11'd271 || counter==11'd272) ? 8'h00 : (counter==11'd3) ? EAV : (counter==11'd273) ? SAV : v_data; assign p[1:0] = 2'b0; wire v_line; // Determines which line to output depending on the line counter. assign v_line = ((line_counter>11'd19 && line_counter<11'd40) || (line_counter>11'd243 && line_counter<11'd264) || (line_counter>11'd282 && line_counter<11'd303) || (line_counter>11'd506 && line_counter<11'd526)) ? 1'b0 : 1'b1; /* // We could define v_line this way, and it will generate more logic // but the max frequency will go up. reg v_line; always @(posedge clk) begin if (rst) v_line <= 1'b0; else begin case (line_counter) 11'd19: v_line<=1'b0; 11'd40: v_line<=1'b1; 11'd243: v_line<=1'b0; 11'd264: v_line<=1'b1; 11'd282: v_line<=1'b0; 11'd303: v_line<=1'b1; 11'd506: v_line<=1'b0; 11'd526: v_line<=1'b1; endcase // case(line_counter) end // else: !if(rst) end */ assign v_addr = (counter-11'd276); VideoMem videomem( .data(v_data), .ADDR(v_addr), .LINENO(v_line), .CLK(clock) ); /* synthesis translate_off */ assign v_data = v_line ? 8'hAA : 8'h55; /* synthesis translate_on */ // The counter used for I2C and for counting bytes within a line. // This counter is shared, so it had a contional reset for when // it's in the sendingVideo state. always @(posedge clk) if (rst || rst_count) counter<=11'b0; else if(counter==11'd1716 && cs==sendingVideo) counter<=11'b0; else counter<=counter+1; // The counter used for keeping track of the current line always @(posedge clk) if (rst || rst_line_count) line_counter<=10'd1; else if (line_counter==10'd525) line_counter<=10'd1; else if (counter==11'd1716) line_counter<=line_counter+1; // Counter to keep track of how many bits we've shifted out of // the shift register. always @(posedge clk) if (rst) num_bits<=5'b0; else if (sda_shift) num_bits<=num_bits+1; always@(posedge clk) begin if (rst) cs<=initialState; else cs<=ns; end // always@ (posedge clk) // State machine. always @(cs or counter or num_bits) begin ns<=initialState; case (cs) initialState: if (&counter[6:0]) ns<=sendingI2C; sendingI2C: if (num_bits==5'h1c && &counter[6:0]) ns<=resetCounter; else ns<=sendingI2C; resetCounter: ns<=sendingVideo; sendingVideo: ns<=sendingVideo; default: ns<=2'bXX; endcase // case(cs) end // always @ (cs) endmodule // Videomodule // Shift register that shifts left // It will initialize the register to D on reset module ShiftRegister(D,Q,clk,rst,shift); parameter width = 29; input [width-1:0] D; output Q; input clk,rst,shift; reg [width-1:0] completeQ; assign Q = completeQ[width-1]; always @(posedge clk) begin if (rst) completeQ <= D; else if (shift) completeQ<={completeQ[width-2:0],1'b1}; end // always @ (posedge clk) endmodule