mirror of
https://github.com/alangarf/apple-one.git
synced 2025-01-22 14:30:04 +00:00
wip of the pipeline VGA module. stupid yosys bug, but testbench looks ok
This commit is contained in:
parent
2432225d01
commit
20919fa726
@ -33,157 +33,11 @@ module apple1_tb;
|
||||
|
||||
initial begin
|
||||
|
||||
// force core_top.clk_div = 0;
|
||||
// force core_top.cpu_clken = 0;
|
||||
// force core_top.hard_reset = 0;
|
||||
// force core_top.reset_cnt = 0;
|
||||
|
||||
// force core_top.my_cpu.arlet_cpu.AB = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.PC = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ABL = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ABH = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.DIHOLD = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.IRHOLD = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.IRHOLD_valid = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.C = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.Z = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.I = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.D = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.V = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.N = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.AI = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.BI = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.DO = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.WE = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.CI = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.NMI_edge = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.regsel = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.PC_inc = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.PC_temp = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.src_reg = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.dst_reg = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.index_y = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.load_reg = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.inc = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.write_back = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.load_only = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.store = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.adc_sbc = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.compare = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.shift = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.rotate = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.backwards = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.cond_true = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.cond_code = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.shift_right = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.alu_shift_right = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.op = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.alu_op = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.adc_bcd = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.adj_bcd = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.bit_ins = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.plp = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.php = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.clc = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.sed = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.cli = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.sei = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.clv = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.brk = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.res = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.write_register = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ADJL = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ADJH = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.NMI_1 = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.OUT = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.CO = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.N = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.HC = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.AI7 = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.BI7 = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.temp_logic = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.temp_BI = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.temp_l = 0;
|
||||
// force core_top.my_cpu.arlet_cpu.ALU.temp_h = 0;
|
||||
|
||||
clk25 = 1'b0;
|
||||
uart_rx = 1'b1;
|
||||
rst_n = 1'b0;
|
||||
#40 rst_n = 1'b1;
|
||||
|
||||
// release core_top.clk_div;
|
||||
// release core_top.cpu_clken;
|
||||
// release core_top.hard_reset;
|
||||
// release core_top.reset_cnt;
|
||||
// release core_top.my_cpu.arlet_cpu.AB;
|
||||
// release core_top.my_cpu.arlet_cpu.PC;
|
||||
// release core_top.my_cpu.arlet_cpu.ABL;
|
||||
// release core_top.my_cpu.arlet_cpu.ABH;
|
||||
// release core_top.my_cpu.arlet_cpu.DIHOLD;
|
||||
// release core_top.my_cpu.arlet_cpu.IRHOLD;
|
||||
// release core_top.my_cpu.arlet_cpu.IRHOLD_valid;
|
||||
// release core_top.my_cpu.arlet_cpu.C;
|
||||
// release core_top.my_cpu.arlet_cpu.Z;
|
||||
// release core_top.my_cpu.arlet_cpu.I;
|
||||
// release core_top.my_cpu.arlet_cpu.D;
|
||||
// release core_top.my_cpu.arlet_cpu.V;
|
||||
// release core_top.my_cpu.arlet_cpu.N;
|
||||
// release core_top.my_cpu.arlet_cpu.AI;
|
||||
// release core_top.my_cpu.arlet_cpu.BI;
|
||||
// release core_top.my_cpu.arlet_cpu.DO;
|
||||
// release core_top.my_cpu.arlet_cpu.WE;
|
||||
// release core_top.my_cpu.arlet_cpu.CI;
|
||||
// release core_top.my_cpu.arlet_cpu.NMI_edge;
|
||||
// release core_top.my_cpu.arlet_cpu.regsel;
|
||||
// release core_top.my_cpu.arlet_cpu.PC_inc;
|
||||
// release core_top.my_cpu.arlet_cpu.PC_temp;
|
||||
// release core_top.my_cpu.arlet_cpu.src_reg;
|
||||
// release core_top.my_cpu.arlet_cpu.dst_reg;
|
||||
// release core_top.my_cpu.arlet_cpu.index_y;
|
||||
// release core_top.my_cpu.arlet_cpu.load_reg;
|
||||
// release core_top.my_cpu.arlet_cpu.inc;
|
||||
// release core_top.my_cpu.arlet_cpu.write_back;
|
||||
// release core_top.my_cpu.arlet_cpu.load_only;
|
||||
// release core_top.my_cpu.arlet_cpu.store;
|
||||
// release core_top.my_cpu.arlet_cpu.adc_sbc;
|
||||
// release core_top.my_cpu.arlet_cpu.compare;
|
||||
// release core_top.my_cpu.arlet_cpu.shift;
|
||||
// release core_top.my_cpu.arlet_cpu.rotate;
|
||||
// release core_top.my_cpu.arlet_cpu.backwards;
|
||||
// release core_top.my_cpu.arlet_cpu.cond_true;
|
||||
// release core_top.my_cpu.arlet_cpu.cond_code;
|
||||
// release core_top.my_cpu.arlet_cpu.shift_right;
|
||||
// release core_top.my_cpu.arlet_cpu.alu_shift_right;
|
||||
// release core_top.my_cpu.arlet_cpu.op;
|
||||
// release core_top.my_cpu.arlet_cpu.alu_op;
|
||||
// release core_top.my_cpu.arlet_cpu.adc_bcd;
|
||||
// release core_top.my_cpu.arlet_cpu.adj_bcd;
|
||||
// release core_top.my_cpu.arlet_cpu.bit_ins;
|
||||
// release core_top.my_cpu.arlet_cpu.plp;
|
||||
// release core_top.my_cpu.arlet_cpu.php;
|
||||
// release core_top.my_cpu.arlet_cpu.clc;
|
||||
// release core_top.my_cpu.arlet_cpu.sec;
|
||||
// release core_top.my_cpu.arlet_cpu.cld;
|
||||
// release core_top.my_cpu.arlet_cpu.sed;
|
||||
// release core_top.my_cpu.arlet_cpu.sei;
|
||||
// release core_top.my_cpu.arlet_cpu.clv;
|
||||
// release core_top.my_cpu.arlet_cpu.brk;
|
||||
// release core_top.my_cpu.arlet_cpu.res;
|
||||
// release core_top.my_cpu.arlet_cpu.write_register;
|
||||
// release core_top.my_cpu.arlet_cpu.ADJL;
|
||||
// release core_top.my_cpu.arlet_cpu.ADJH;
|
||||
// release core_top.my_cpu.arlet_cpu.NMI_1;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.OUT;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.CO;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.N;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.HC;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.AI7;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.BI7;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.temp_logic;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.temp_BI;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.temp_l;
|
||||
// release core_top.my_cpu.arlet_cpu.ALU.temp_h;
|
||||
|
||||
$display("Starting...");
|
||||
$dumpfile("apple1_top_tb.vcd");
|
||||
$dumpvars;
|
||||
|
2
iverilog/run_vga_tb.sh
Executable file
2
iverilog/run_vga_tb.sh
Executable file
@ -0,0 +1,2 @@
|
||||
iverilog -DSIM -g2005 -s vga_tb -o vga_tb -c vga_files.txt
|
||||
vvp vga_tb
|
4
iverilog/vga_files.txt
Normal file
4
iverilog/vga_files.txt
Normal file
@ -0,0 +1,4 @@
|
||||
../rtl/vga/vga.v
|
||||
../rtl/vga/vram.v
|
||||
../rtl/vga/font_rom.v
|
||||
vga_tb.v
|
95
iverilog/vga_tb.v
Normal file
95
iverilog/vga_tb.v
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
// Description: Top level test bench for apple1_top
|
||||
//
|
||||
// Author.....: Niels A. Moseley
|
||||
// Date.......: 26-1-2018
|
||||
//
|
||||
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module vga_tb;
|
||||
|
||||
reg clk25, rst, address, w_en, blink_clken;
|
||||
reg [7:0] din;
|
||||
wire vga_h_sync, vga_v_sync, vga_red, vga_grn, vga_blu;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Setup dumping of data for inspection
|
||||
|
||||
initial begin
|
||||
|
||||
clk25 = 1'b0;
|
||||
rst = 1'b0;
|
||||
address = 1'b0;
|
||||
w_en = 1'b0;
|
||||
blink_clken = 1'b0;
|
||||
din = 8'd0;
|
||||
|
||||
#5
|
||||
rst = 1'b1;
|
||||
#5
|
||||
rst = 1'b0;
|
||||
|
||||
$display("Starting...");
|
||||
$dumpfile("vga_tb.vcd");
|
||||
$dumpvars;
|
||||
|
||||
//#180000
|
||||
//uart_rx = 1'b0;
|
||||
//#400
|
||||
//uart_rx = 1'b1;
|
||||
//#400
|
||||
//uart_rx = 1'b0;
|
||||
//#400
|
||||
//uart_rx = 1'b1;
|
||||
//#800
|
||||
//uart_rx = 1'b0;
|
||||
//#1600
|
||||
//uart_rx = 1'b1;
|
||||
|
||||
|
||||
#50000000 $display("Stopping...");
|
||||
$finish;
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Clock
|
||||
|
||||
always
|
||||
#20 clk25 = !clk25;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Core of system
|
||||
vga my_vga (
|
||||
.clk25(clk25),
|
||||
.enable(1'b1),
|
||||
.rst(rst),
|
||||
.vga_h_sync(vga_h_sync),
|
||||
.vga_v_sync(vga_v_sync),
|
||||
.vga_red(vga_red),
|
||||
.vga_grn(vga_grn),
|
||||
.vga_blu(vga_blu),
|
||||
.address(address),
|
||||
.w_en(w_en),
|
||||
.din(din),
|
||||
.blink_clken(blink_clken)
|
||||
);
|
||||
|
||||
endmodule
|
1088
roms/vga_font.bin
1088
roms/vga_font.bin
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,67 @@
|
||||
000001
|
||||
000010
|
||||
000011
|
||||
000100
|
||||
000101
|
||||
000110
|
||||
000111
|
||||
001000
|
||||
001001
|
||||
001010
|
||||
001011
|
||||
001100
|
||||
001101
|
||||
001110
|
||||
001111
|
||||
010000
|
||||
010001
|
||||
010010
|
||||
010011
|
||||
010100
|
||||
010101
|
||||
010110
|
||||
010111
|
||||
011000
|
||||
011001
|
||||
011010
|
||||
011011
|
||||
011100
|
||||
011101
|
||||
011110
|
||||
011111
|
||||
100000
|
||||
100001
|
||||
100010
|
||||
100011
|
||||
100100
|
||||
100101
|
||||
100110
|
||||
100111
|
||||
101000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
100000
|
||||
|
54
rtl/vga/font_rom.v
Normal file
54
rtl/vga/font_rom.v
Normal file
@ -0,0 +1,54 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
// Description: 8KB RAM for system
|
||||
//
|
||||
// Author.....: Alan Garfield
|
||||
// Date.......: 3-2-2018
|
||||
//
|
||||
|
||||
module font_rom(
|
||||
input clk, // clock signal
|
||||
input [5:0] character, // address bus
|
||||
input [3:0] pixel, // address of the pixel to output
|
||||
input [4:0] line, // address of the line to output
|
||||
output reg out // single pixel from address and pixel pos
|
||||
);
|
||||
|
||||
`ifdef SIM
|
||||
parameter ROM_FILENAME = "../roms/vga_font.bin";
|
||||
`else
|
||||
parameter ROM_FILENAME = "../../roms/vga_font.bin";
|
||||
`endif
|
||||
|
||||
reg [7:0] rom[0:639];
|
||||
|
||||
initial
|
||||
$readmemb(ROM_FILENAME, rom, 0, 639);
|
||||
|
||||
// double width of pixel by ignoring bit 0
|
||||
wire [2:0] pixel_ptr;
|
||||
assign pixel_ptr = (3'h7 - pixel[3:1]);
|
||||
|
||||
// double height of pixel by ignoring bit 0
|
||||
wire [3:0] line_ptr = line[4:1];
|
||||
|
||||
always @(posedge clk)
|
||||
out <= rom[(character * 10) + {2'd0, line_ptr}][pixel_ptr];
|
||||
|
||||
endmodule
|
||||
|
317
rtl/vga/vga.v
317
rtl/vga/vga.v
@ -10,246 +10,169 @@ module vga(
|
||||
input address, // address bus
|
||||
input w_en, // active high write enable strobe
|
||||
input [7:0] din, // 8-bit data bas (input)
|
||||
input clr_screen_btn, // active high clear screen button
|
||||
input blink_clken, // cursor blink enable strobe
|
||||
output [15:0] debug
|
||||
input blink_clken // cursor blink enable strobe
|
||||
);
|
||||
|
||||
reg [4:0] c_rom[0:447] /* synthesis syn_ramstyle = "block_ram" */;
|
||||
initial begin
|
||||
$readmemb("../../roms/vga_font.bin", c_rom, 0, 447);
|
||||
end
|
||||
|
||||
reg [9:0] vram_r_addr;
|
||||
reg [9:0] vram_w_addr;
|
||||
reg vram_r_en;
|
||||
reg vram_w_en;
|
||||
reg [5:0] vram_din;
|
||||
reg [5:0] vram_dout;
|
||||
|
||||
vram my_vram(
|
||||
.clk(clk25),
|
||||
.read_addr(vram_r_addr),
|
||||
.write_addr(vram_w_addr),
|
||||
.r_en(vram_r_en),
|
||||
.w_en(vram_w_en),
|
||||
.din(vram_din),
|
||||
.dout(vram_dout)
|
||||
);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VGA Sync Generation
|
||||
|
||||
// video structure constants
|
||||
parameter hpixels = 800; // horizontal pixels per line
|
||||
parameter vlines = 521; // vertical lines per frame
|
||||
parameter hpulse = 96; // hsync pulse length
|
||||
parameter vpulse = 2; // vsync pulse length
|
||||
parameter h_pixels = 799; // horizontal pixels per line
|
||||
parameter v_lines = 520; // vertical lines per frame
|
||||
parameter h_pulse = 96; // hsync pulse length
|
||||
parameter v_pulse = 2; // vsync pulse length
|
||||
parameter hbp = 144; // end of horizontal back porch
|
||||
parameter hfp = 784; // beginning of horizontal front porch
|
||||
parameter vbp = 31; // end of vertical back porch
|
||||
parameter vfp = 511; // beginning of vertical front porch
|
||||
|
||||
// registers for storing the horizontal & vertical counters
|
||||
reg [9:0] hc;
|
||||
reg [9:0] vc;
|
||||
reg [5:0] hpos;
|
||||
reg [4:0] vpos;
|
||||
reg [3:0] hdot;
|
||||
reg [4:0] vdot;
|
||||
reg [9:0] h_cnt;
|
||||
reg [9:0] v_cnt;
|
||||
wire [3:0] h_dot;
|
||||
reg [4:0] v_dot;
|
||||
|
||||
reg [5:0] h_cursor;
|
||||
reg [4:0] v_cursor;
|
||||
|
||||
wire vga_h_act;
|
||||
wire vga_v_act;
|
||||
wire h_active;
|
||||
wire v_active;
|
||||
assign h_active = (h_cnt >= hbp && h_cnt < hfp);
|
||||
assign v_active = (v_cnt >= vbp && v_cnt < vfp);
|
||||
|
||||
assign vga_h_act = (hc >= hbp && hc < hfp);
|
||||
assign vga_v_act = (vc >= vbp && vc < vfp);
|
||||
|
||||
assign vga_h_sync = (hc < hpulse) ? 0 : 1;
|
||||
assign vga_v_sync = (vc < vpulse) ? 0 : 1;
|
||||
//assign vblank = (vc >= vbp && vc < vfp) ? 0:1;
|
||||
|
||||
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
|
||||
// reset vertical counters
|
||||
vc <= 0;
|
||||
vdot <= 0;
|
||||
vpos <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg out;
|
||||
assign vga_red = out;
|
||||
assign vga_grn = out;
|
||||
assign vga_blu = out;
|
||||
|
||||
reg [8:0] cur_chr_offset;
|
||||
reg [9:0] v_pos_offset;
|
||||
reg [3:0] v_offset;
|
||||
reg [2:0] h_offset;
|
||||
reg blink;
|
||||
assign vga_h_sync = (h_cnt < h_pulse) ? 0 : 1;
|
||||
assign vga_v_sync = (v_cnt < v_pulse) ? 0 : 1;
|
||||
|
||||
always @(posedge clk25 or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
vram_r_addr = 10'd0;
|
||||
vram_r_en = 1'b0;
|
||||
h_cnt <= 10'd0;
|
||||
v_cnt <= 10'd0;
|
||||
v_dot <= 5'd0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// get the current character from vram and build
|
||||
// offset to map into character ROM (5x7 font)
|
||||
if (blink && (hpos == h_cursor && vpos == v_cursor))
|
||||
cur_chr_offset = 9'd0; // the @ character
|
||||
if (h_cnt < h_pixels)
|
||||
h_cnt <= h_cnt + 1;
|
||||
|
||||
else
|
||||
begin
|
||||
vram_r_en = 1'b1;
|
||||
v_pos_offset = (vpos * 40);
|
||||
vram_r_addr = (v_pos_offset + {4'b0, hpos});
|
||||
cur_chr_offset = (vram_dout * 7);
|
||||
// reset horizontal counters
|
||||
h_cnt <= 0;
|
||||
|
||||
//cur_chr_offset <= (v_ram[hpos + (40 * vpos)] * 7);
|
||||
end
|
||||
|
||||
case ({vga_h_act, vga_v_act})
|
||||
default:
|
||||
// outside display area
|
||||
out = 1'b0;
|
||||
|
||||
2'b11:
|
||||
if (v_cnt < v_lines)
|
||||
begin
|
||||
// we're inside the visible screen display frame
|
||||
//
|
||||
// scan doubling is achieved by ignoring bit 0 of both vdot
|
||||
// and hdot counters, in affect doubling the pixel size
|
||||
// (each pixel becomes screen pixels)
|
||||
case (vdot[4:1])
|
||||
4'b0000,
|
||||
4'b0001,
|
||||
4'b1001:
|
||||
v_cnt <= v_cnt + 1;
|
||||
|
||||
// count 20 rows, so 480px / 20 = 24 rows
|
||||
if (v_active)
|
||||
begin
|
||||
// blank lines for spacing
|
||||
out = 1'b0;
|
||||
end
|
||||
v_dot <= v_dot + 1;
|
||||
|
||||
default:
|
||||
if (v_dot == 5'd19)
|
||||
v_dot <= 0;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
// work out character rom offset for current line
|
||||
// taking away 2 from counter to allow for the two
|
||||
// blank preceding lines
|
||||
v_offset = (vdot[4:1] - 2);
|
||||
|
||||
case (hdot[3:1])
|
||||
3'b000,
|
||||
3'b110,
|
||||
3'b111:
|
||||
begin
|
||||
// blank columns for spacing
|
||||
out = 1'b0;
|
||||
// reset vertical counters
|
||||
v_cnt <= 0;
|
||||
v_dot <= 0;
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
// work out the character rom offset for the current
|
||||
// column. We reverse the dot pattern by subtracting
|
||||
// the column from the number of pixel in the
|
||||
// character row in rom
|
||||
h_offset = (5 - hdot[3:1]);
|
||||
|
||||
// grab the pixel from the character rom for
|
||||
// the given screen column and line
|
||||
out = c_rom[cur_chr_offset + {5'b0, v_offset}][h_offset];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
reg cls_flag, cls_running;
|
||||
// count 16 pixels, so 640px / 16 = 40 characters
|
||||
assign h_dot = h_active ? h_cnt[3:0] : 4'd0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Character ROM
|
||||
|
||||
wire [5:0] font_char;
|
||||
wire [3:0] font_pixel;
|
||||
wire [4:0] font_line;
|
||||
wire font_out;
|
||||
|
||||
font_rom my_font_rom(
|
||||
.clk(clk25),
|
||||
.character(font_char),
|
||||
.pixel(font_pixel),
|
||||
.line(font_line),
|
||||
.out(font_out)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Video RAM
|
||||
|
||||
wire [9:0] vram_r_addr;
|
||||
reg [9:0] vram_w_addr;
|
||||
reg vram_w_en;
|
||||
reg [5:0] vram_din;
|
||||
wire [5:0] vram_dout;
|
||||
|
||||
vram my_vram(
|
||||
.clk(clk25),
|
||||
.rst(rst),
|
||||
.read_addr(vram_r_addr),
|
||||
.write_addr(vram_w_addr),
|
||||
.r_en(h_active),
|
||||
.w_en(vram_w_en),
|
||||
.din(vram_din),
|
||||
.dout(vram_dout)
|
||||
);
|
||||
|
||||
|
||||
reg [5:0] vram_h_addr;
|
||||
reg [9:0] vram_v_addr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Video Signal Generation
|
||||
|
||||
always @(posedge clk25 or posedge rst) begin
|
||||
if (rst) begin
|
||||
vram_h_addr <= 0;
|
||||
vram_v_addr <= 0;
|
||||
end else begin
|
||||
// start the pipeline for reading vram and font details
|
||||
// 3 pixel clock cycles early
|
||||
if (h_dot == 4'hC)
|
||||
vram_h_addr <= vram_h_addr + 1;
|
||||
|
||||
// advance to next row when last display line is reached for row
|
||||
if (v_dot == 5'd19 && h_cnt == 10'd0)
|
||||
vram_v_addr <= vram_v_addr + 10'h28;
|
||||
|
||||
// clear the address registers if we're not in visible area
|
||||
if (~h_active)
|
||||
vram_h_addr <= 0;
|
||||
if (~v_active)
|
||||
vram_v_addr <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
assign vram_r_addr = ({4'd0, vram_h_addr} + vram_v_addr);
|
||||
assign font_char = vram_dout;
|
||||
assign font_pixel = h_dot + 1; // offset by one to get pixel into right cycle,
|
||||
// font output one pixel clk behind
|
||||
assign font_line = v_dot;
|
||||
|
||||
assign vga_red = font_out;
|
||||
assign vga_grn = font_out;
|
||||
assign vga_blu = font_out;
|
||||
|
||||
reg char_seen;
|
||||
|
||||
always @(posedge clk25 or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
blink <= 1'b1;
|
||||
h_cursor <= 6'd0;
|
||||
v_cursor <= 5'd0;
|
||||
char_seen <= 0;
|
||||
debug <= 0;
|
||||
cls_running <= 0;
|
||||
cls_flag <= 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (cls_flag || clr_screen_btn)
|
||||
begin
|
||||
if ((vpos == 0) && (hpos == 0))
|
||||
cls_running <= 1;
|
||||
|
||||
if (cls_running)
|
||||
begin
|
||||
// clear the vram using the position pointers
|
||||
// very similar to the original apple 1 :)
|
||||
vram_w_addr <= ((vpos * 40) + {4'b0, hpos});
|
||||
vram_din <= 6'd0;
|
||||
vram_w_en <= 1;
|
||||
|
||||
if ((vpos == 23) && (hpos == 40))
|
||||
begin
|
||||
cls_running <= 0;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
cls_flag <= 0;
|
||||
end
|
||||
end
|
||||
begin
|
||||
vram_w_en <= 0;
|
||||
|
||||
@ -258,7 +181,6 @@ module vga(
|
||||
if (enable & w_en & ~char_seen)
|
||||
begin
|
||||
// incoming character
|
||||
debug <= {8'd0, din};
|
||||
char_seen <= 1;
|
||||
|
||||
case(din)
|
||||
@ -301,9 +223,6 @@ module vga(
|
||||
char_seen <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (blink_clken)
|
||||
blink <= ~blink;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
module vram(
|
||||
input clk, // clock signal
|
||||
input rst, //
|
||||
input [9:0] read_addr, // read address bus
|
||||
input [9:0] write_addr, // write address bus
|
||||
input r_en, // active high read enable strobe
|
||||
@ -33,7 +34,7 @@ module vram(
|
||||
);
|
||||
|
||||
`ifdef SIM
|
||||
parameter RAM_FILENAME = "../roms/ram.hex";
|
||||
parameter RAM_FILENAME = "../roms/vga_vram.bin";
|
||||
`else
|
||||
parameter RAM_FILENAME = "../../roms/vga_vram.bin";
|
||||
`endif
|
||||
@ -41,13 +42,19 @@ module vram(
|
||||
reg [5:0] ram_data[0:1023];
|
||||
|
||||
initial
|
||||
$readmemb(RAM_FILENAME, ram_data, 0, 1024);
|
||||
$readmemb(RAM_FILENAME, ram_data, 0, 1023);
|
||||
|
||||
always @(posedge clk)
|
||||
always @(posedge clk or posedge rst )
|
||||
begin
|
||||
if (r_en) dout <= ram_data[read_addr];
|
||||
if (rst)
|
||||
dout <= 0;
|
||||
else
|
||||
begin
|
||||
//if (r_en) dout <= ram_data[read_addr];
|
||||
dout <= ram_data[read_addr];
|
||||
if (w_en) ram_data[write_addr] <= din;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user