From 4fef9bc10b16392f46f1be086a01818c9a23ca02 Mon Sep 17 00:00:00 2001 From: Alan Garfield Date: Mon, 29 Jan 2018 22:53:16 +1100 Subject: [PATCH] Initial VGA module, still WIP, just outputs fixed VRAM --- boards/ice40hx8k/ice40hx8k.pcf | 7 ++ boards/ice40hx8k_yosys/Makefile | 1 + rtl/apple1.v | 19 +++++ rtl/boards/ice40hx8k/apple1_hx8k.v | 12 +++ rtl/vga/vga.v | 127 ++++++++++++++--------------- 5 files changed, 98 insertions(+), 68 deletions(-) diff --git a/boards/ice40hx8k/ice40hx8k.pcf b/boards/ice40hx8k/ice40hx8k.pcf index 8af8e08..df220e5 100644 --- a/boards/ice40hx8k/ice40hx8k.pcf +++ b/boards/ice40hx8k/ice40hx8k.pcf @@ -35,6 +35,13 @@ set_io button[2] F1 set_io button[1] F2 set_io button[0] G1 +### VGA Display +set_io vga_h_sync C2 +set_io vga_v_sync D1 +set_io vga_red B1 +set_io vga_grn B2 +set_io vga_blu C1 + ### TM1638 Display #set_io tm_clk P1 #set_io tm_dio P2 diff --git a/boards/ice40hx8k_yosys/Makefile b/boards/ice40hx8k_yosys/Makefile index bbb22a6..ac6781a 100644 --- a/boards/ice40hx8k_yosys/Makefile +++ b/boards/ice40hx8k_yosys/Makefile @@ -51,6 +51,7 @@ $(BUILDDIR)/apple1.blif: $(SOURCEDIR)/apple1.v \ $(SOURCEDIR)/cpu/arlet/cpu.v \ $(SOURCEDIR)/uart/uart.v \ $(SOURCEDIR)/uart/async_tx_rx.v \ + $(SOURCEDIR)/vga/vga.v \ $(SOURCEDIR)/ps2keyboard/ps2keyboard.v \ $(SOURCEDIR)/boards/ice40hx8k/clock_pll.v \ $(SOURCEDIR)/boards/ice40hx8k/apple1_hx8k.v diff --git a/rtl/apple1.v b/rtl/apple1.v index 75de670..b958d67 100644 --- a/rtl/apple1.v +++ b/rtl/apple1.v @@ -35,6 +35,13 @@ module apple1( input ps2_clk, // PS/2 keyboard serial clock input input ps2_din, // PS/2 keyboard serial data input + // Outputs to VGA display + output vga_h_sync, // hozizontal VGA sync pulse + output vga_v_sync, // vertical VGA sync pulse + output reg vga_red, // red VGA signal + output reg vga_grn, // green VGA signal + output reg vga_blu, // blue VGA signal + // Debugging ports output [15:0] pc_monitor // spy for program counter / debugging ); @@ -163,6 +170,18 @@ module apple1( .dout(ps2_dout) ); + // VGA Display interface + vga my_vga( + .clk25(clk25), + .in(), + .in_stb(), + .vga_h_sync(vga_h_sync), + .vga_v_sync(vga_v_sync), + .vga_red(vga_red), + .vga_grn(vga_grn), + .vga_blu(vga_blu) + ); + ////////////////////////////////////////////////////////////////////////// // CPU Data In MUX diff --git a/rtl/boards/ice40hx8k/apple1_hx8k.v b/rtl/boards/ice40hx8k/apple1_hx8k.v index f83c594..f3a9081 100644 --- a/rtl/boards/ice40hx8k/apple1_hx8k.v +++ b/rtl/boards/ice40hx8k/apple1_hx8k.v @@ -30,6 +30,13 @@ module apple1_top( output uart_tx, // asynchronous serial data output to computer output uart_cts, // clear to send flag to computer + // Outputs to VGA display + output vga_h_sync, // hozizontal VGA sync pulse + output vga_v_sync, // vertical VGA sync pulse + output reg vga_red, // red VGA signal + output reg vga_grn, // green VGA signal + output reg vga_blu, // blue VGA signal + // Debugging ports output [7:0] led, // 8 LEDs on the iCE40HX8K board @@ -59,6 +66,11 @@ module apple1_top( .uart_rx(uart_rx), .uart_tx(uart_tx), .uart_cts(uart_cts), + .vga_h_sync(vga_h_sync), + .vga_v_sync(vga_v_sync), + .vga_red(vga_red), + .vga_grn(vga_grn), + .vga_blu(vga_blu), .pc_monitor(pc_monitor) ); diff --git a/rtl/vga/vga.v b/rtl/vga/vga.v index 73b1c09..01ce49b 100644 --- a/rtl/vga/vga.v +++ b/rtl/vga/vga.v @@ -1,5 +1,5 @@ module vga( - input clk, + input clk25, input [6:0] in, input in_stb, output vga_h_sync, @@ -12,20 +12,10 @@ module vga( reg [5:0] v_ram[0:959] /* synthesis syn_ramstyle = "block_ram" */; reg [4:0] c_rom[0:447] /* synthesis syn_ramstyle = "block_ram" */; initial begin - $readmemb("../roms/vga_vram.bin", v_ram, 0, 959); - $readmemb("../roms/vga_font.bin", c_rom, 0, 447); + $readmemb("../../roms/vga_vram.bin", v_ram, 0, 959); + $readmemb("../../roms/vga_font.bin", c_rom, 0, 447); end - // generate 25MHz pixel clock enable - reg vga_cnt; - wire vga_clk_en; - - always @(posedge clk) - begin - vga_cnt <= vga_cnt + 1; - end - assign vga_clk_en = vga_cnt; - // video structure constants parameter hpixels = 800; // horizontal pixels per line parameter vlines = 521; // vertical lines per frame @@ -44,58 +34,8 @@ module vga( reg [3:0] hdot; reg [4:0] vdot; - always @(posedge clk) - begin - if (vga_clk_en) - begin - if (hc < hpixels - 1) - begin - hc <= hc + 1; - - // count 16 pixels, so 640px / 16 = 40 characters - if (vga_h_act) - begin - hdot <= hdot + 1; - - if (hdot == 4'hF) - begin - hdot <= 0; - hpos <= hpos + 1; - end - end - end - else - begin - // reset horizontal counters - hc <= 0; - hdot <= 0; - hpos <= 0; - - if (vc < vlines - 1) - begin - vc <= vc + 1; - - // count 20 rows, so 480px / 20 = 24 rows - if (vga_v_act) - begin - vdot <= vdot + 1; - - if (vdot == 5'd19) - begin - vdot <= 0; - vpos <= vpos + 1; - end - end - end - else - begin - vc <= 0; - vdot <= 0; - vpos <= 0; - end - end - end - end + wire vga_h_act; + wire vga_v_act; assign vga_h_act = (hc >= hbp && hc < hfp); assign vga_v_act = (vc >= vbp && vc < vfp); @@ -104,7 +44,58 @@ module vga( assign vga_v_sync = (vc < vpulse) ? 0 : 1; // assign vblank = (vc >= vbp && vc < vfp) ? 0:1; - always @(posedge clk) + always @(posedge clk25) + begin + if (hc < hpixels - 1) + begin + hc <= hc + 1; + + // count 16 pixels, so 640px / 16 = 40 characters + if (vga_h_act) + begin + hdot <= hdot + 1; + + if (hdot == 4'hF) + begin + hdot <= 0; + hpos <= hpos + 1; + end + end + end + else + begin + // reset horizontal counters + hc <= 0; + hdot <= 0; + hpos <= 0; + + if (vc < vlines - 1) + begin + vc <= vc + 1; + + // count 20 rows, so 480px / 20 = 24 rows + if (vga_v_act) + begin + vdot <= vdot + 1; + + if (vdot == 5'd19) + begin + vdot <= 0; + vpos <= vpos + 1; + end + end + end + else + begin + vc <= 0; + vdot <= 0; + vpos <= 0; + end + end + end + + + always @(posedge clk25) begin if (~(vga_h_act && vga_v_act)) begin @@ -127,11 +118,11 @@ module vga( reg [5:0] cur_pos; reg stb; - always @(posedge clk) + always @(posedge clk25) begin if (in_stb & ~stb) begin - v_ram[cur_pos] <= {~in[6], in[4:0]}; + v_ram[{4'b0, cur_pos}] <= {~in[6], in[4:0]}; stb <= 1; cur_pos <= cur_pos + 1; end