module video ( input clk, input ce, input [14:0] addr, input [15:0] dataIn, input [1:0] wr, output reg hsync, output reg vsync, output _hblank, output _vblank, output video_en, output pixelOut ); localparam kVisibleWidth = 128, kTotalWidth = 176, kVisibleHeightStart = 21, kVisibleHeightEnd = 362, kTotalHeight = 370, kHsyncStart = 135, kHsyncEnd = 151, kVsyncStart = 365, kVsyncEnd = 369, kPixelLatency = 1; // number of clk8 cycles from xpos==0 to when pixel data actually exits the video shift register localparam videoStart = 'hA700 - (kVisibleHeightStart * kVisibleWidth/2); reg [7:0] xpos; reg [9:0] ypos; assign _hblank = ~(xpos >= kVisibleWidth); assign _vblank = ~(ypos < kVisibleHeightStart || ypos > kVisibleHeightEnd); wire [15:0] scrData; vram buff ( .clock(clk), .data(dataIn), .wraddress(addr[13:0]), .byteena_a(wr), .wren(ram_wr), .rdaddress(videoStart[14:1] + {ypos[8:0], xpos[6:2]}), .q(scrData) ); reg ram_wr; always @(posedge clk) begin reg old_wr; old_wr <= |wr; ram_wr <= (~old_wr & |wr); end reg [3:0] cycle; always @(posedge clk) if(ce) cycle <= cycle + 1'd1; always @(posedge clk) begin if(ce && !cycle[1:0]) begin if (xpos == kTotalWidth-1) begin xpos <= 0; if (ypos == kTotalHeight-1) ypos <= 0; else ypos <= ypos + 1'b1; end else if (!xpos && cycle) begin xpos <= 0; end else begin xpos <= xpos + 1'b1; end hsync <= (xpos >= kHsyncStart+kPixelLatency && xpos <= kHsyncEnd+kPixelLatency); vsync <= (ypos >= kVsyncStart && ypos <= kVsyncEnd); end end // a 0 bit is white, and a 1 bit is black // data is shifted out MSB first assign pixelOut = ~shiftRegister[15]; assign video_en = paper[15]; reg [15:0] shiftRegister; reg [15:0] paper; always @(posedge clk) begin if(ce) begin if(_vblank && _hblank && cycle == 2) begin shiftRegister <= scrData; paper <= 16'hFFFF; end else begin shiftRegister <= { shiftRegister[14:0], 1'b1 }; paper <= { paper[14:0], 1'b0 }; end end end endmodule module vram ( input clock, input [15:0] data, input [13:0] wraddress, input [1:0] byteena_a, input wren, input [13:0] rdaddress, output [15:0] q ); altsyncram altsyncram_component ( .address_a (wraddress), .address_b (rdaddress), .byteena_a (byteena_a), .clock0 (clock), .data_a (data), .wren_a (wren), .q_b (q), .aclr0 (1'b0), .aclr1 (1'b0), .addressstall_a (1'b0), .addressstall_b (1'b0), .byteena_b (1'b1), .clock1 (1'b1), .clocken0 (1'b1), .clocken1 (1'b1), .clocken2 (1'b1), .clocken3 (1'b1), .data_b ({16{1'b1}}), .eccstatus (), .q_a (), .rden_a (1'b1), .rden_b (1'b1), .wren_b (1'b0)); defparam altsyncram_component.address_aclr_b = "NONE", altsyncram_component.address_reg_b = "CLOCK0", altsyncram_component.byte_size = 8, altsyncram_component.clock_enable_input_a = "BYPASS", altsyncram_component.clock_enable_input_b = "BYPASS", altsyncram_component.clock_enable_output_b = "BYPASS", altsyncram_component.intended_device_family = "Cyclone V", altsyncram_component.lpm_type = "altsyncram", altsyncram_component.numwords_a = 16384, altsyncram_component.numwords_b = 16384, altsyncram_component.operation_mode = "DUAL_PORT", altsyncram_component.outdata_aclr_b = "NONE", altsyncram_component.outdata_reg_b = "UNREGISTERED", altsyncram_component.power_up_uninitialized = "FALSE", altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", altsyncram_component.widthad_a = 14, altsyncram_component.widthad_b = 14, altsyncram_component.width_a = 16, altsyncram_component.width_b = 16, altsyncram_component.width_byteena_a = 2; endmodule