/*
|
/*
|
* Copyright (c) 2008 Zeus Gomez Marmolejo <zeus@opencores.org>
|
* Copyright (c) 2008 Zeus Gomez Marmolejo <zeus@opencores.org>
|
*
|
*
|
* This file is part of the Zet processor. This processor is free
|
* This file is part of the Zet processor. This processor is free
|
* hardware; you can redistribute it and/or modify it under the terms of
|
* hardware; you can redistribute it and/or modify it under the terms of
|
* the GNU General Public License as published by the Free Software
|
* the GNU General Public License as published by the Free Software
|
* Foundation; either version 3, or (at your option) any later version.
|
* Foundation; either version 3, or (at your option) any later version.
|
*
|
*
|
* Zet is distrubuted in the hope that it will be useful, but WITHOUT
|
* Zet is distrubuted in the hope that it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
* License for more details.
|
* License for more details.
|
*
|
*
|
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
* along with Zet; see the file COPYING. If not, see
|
* along with Zet; see the file COPYING. If not, see
|
* <http://www.gnu.org/licenses/>.
|
* <http://www.gnu.org/licenses/>.
|
*/
|
*/
|
|
|
`timescale 1ns/10ps
|
`timescale 1ns/10ps
|
|
|
module vdu (
|
module vdu (
|
// Wishbone signals
|
// Wishbone signals
|
input wb_clk_i, // 25 Mhz VDU clock
|
input wb_clk_i, // 25 Mhz VDU clock
|
input wb_rst_i,
|
input wb_rst_i,
|
input [15:0] wb_dat_i,
|
input [15:0] wb_dat_i,
|
output reg [15:0] wb_dat_o,
|
output reg [15:0] wb_dat_o,
|
input [11:1] wb_adr_i,
|
input [11:1] wb_adr_i,
|
input wb_we_i,
|
input wb_we_i,
|
input wb_tga_i,
|
input wb_tga_i,
|
input [ 1:0] wb_sel_i,
|
input [ 1:0] wb_sel_i,
|
input wb_stb_i,
|
input wb_stb_i,
|
input wb_cyc_i,
|
input wb_cyc_i,
|
output reg wb_ack_o,
|
output wb_ack_o,
|
|
|
// VGA pad signals
|
// VGA pad signals
|
output reg [ 1:0] vga_red_o,
|
output reg [ 1:0] vga_red_o,
|
output reg [ 1:0] vga_green_o,
|
output reg [ 1:0] vga_green_o,
|
output reg [ 1:0] vga_blue_o,
|
output reg [ 1:0] vga_blue_o,
|
output reg horiz_sync,
|
output reg horiz_sync,
|
output reg vert_sync
|
output reg vert_sync
|
);
|
);
|
|
|
// Net, registers and parameters
|
// Net, registers and parameters
|
|
|
// Synchronization constants, these values are taken from:
|
// Synchronization constants, these values are taken from:
|
// http://tinyvga.com/vga-timing/640x400@70Hz
|
// http://tinyvga.com/vga-timing/640x400@70Hz
|
|
|
parameter HOR_DISP_END = 10'd639; // Last horizontal pixel displayed
|
parameter HOR_DISP_END = 10'd639; // Last horizontal pixel displayed
|
parameter HOR_SYNC_BEG = 10'd655; // Start of horizontal synch pulse
|
parameter HOR_SYNC_BEG = 10'd655; // Start of horizontal synch pulse
|
parameter HOR_SYNC_END = 10'd751; // End of Horizontal Synch pulse
|
parameter HOR_SYNC_END = 10'd751; // End of Horizontal Synch pulse
|
parameter HOR_SCAN_END = 10'd799; // Last pixel in scan line
|
parameter HOR_SCAN_END = 10'd799; // Last pixel in scan line
|
parameter HOR_DISP_CHR = 80; // Number of characters displayed per row
|
parameter HOR_DISP_CHR = 80; // Number of characters displayed per row
|
parameter HOR_VIDEO_ON = 10'd7; // When to start displaying characters
|
parameter HOR_VIDEO_ON = 10'd7; // When to start displaying characters
|
parameter HOR_VIDEO_OFF = 10'd647; // When to stop displaying characters
|
parameter HOR_VIDEO_OFF = 10'd647; // When to stop displaying characters
|
|
|
parameter VER_DISP_END = 9'd400; // last row displayed
|
parameter VER_DISP_END = 9'd400; // last row displayed
|
parameter VER_SYNC_BEG = 9'd411; // start of vertical synch pulse
|
parameter VER_SYNC_BEG = 9'd411; // start of vertical synch pulse
|
parameter VER_SYNC_END = 9'd413; // end of vertical synch pulse
|
parameter VER_SYNC_END = 9'd413; // end of vertical synch pulse
|
parameter VER_SCAN_END = 9'd448; // Last scan row in the frame
|
parameter VER_SCAN_END = 9'd448; // Last scan row in the frame
|
parameter VER_DISP_CHR = 6'd25; // Number of character rows displayed
|
parameter VER_DISP_CHR = 6'd25; // Number of character rows displayed
|
|
|
reg cursor_on_v;
|
reg cursor_on_v;
|
reg cursor_on_h;
|
reg cursor_on_h;
|
reg video_on_v;
|
reg video_on_v;
|
reg video_on_h;
|
reg video_on_h;
|
reg [9:0] h_count;
|
reg [9:0] h_count;
|
reg [8:0] v_count; // 0 to VER_SCAN_END
|
reg [8:0] v_count; // 0 to VER_SCAN_END
|
reg [22:0] blink_count;
|
reg [22:0] blink_count;
|
|
|
// Character generator ROM
|
// Character generator ROM
|
wire char_cs;
|
wire char_cs;
|
wire char_we;
|
wire char_we;
|
wire [11:0] char_addr;
|
wire [11:0] char_addr;
|
wire [7:0] char_data_in;
|
wire [7:0] char_data_in;
|
wire [7:0] char_data_out;
|
wire [7:0] char_data_out;
|
|
|
// Control registers
|
// Control registers
|
reg [3:0] reg_adr;
|
reg [3:0] reg_adr;
|
reg [6:0] reg_hcursor; // 80 columns
|
reg [6:0] reg_hcursor; // 80 columns
|
reg [4:0] reg_vcursor; // 25 rows
|
reg [4:0] reg_vcursor; // 25 rows
|
reg [3:0] reg_cur_start;
|
reg [3:0] reg_cur_start;
|
reg [3:0] reg_cur_end;
|
reg [3:0] reg_cur_end;
|
|
|
wire wr_adr;
|
wire wr_adr;
|
wire wr_reg;
|
wire wr_reg;
|
wire write;
|
wire write;
|
wire wr_hcursor;
|
wire wr_hcursor;
|
wire wr_vcursor;
|
wire wr_vcursor;
|
wire wr_cur_start;
|
wire wr_cur_start;
|
wire wr_cur_end;
|
wire wr_cur_end;
|
|
|
// Video shift register
|
// Video shift register
|
reg [7:0] vga_shift;
|
reg [7:0] vga_shift;
|
reg [2:0] vga_fg_colour;
|
reg [2:0] vga_fg_colour;
|
reg [2:0] vga_bg_colour;
|
reg [2:0] vga_bg_colour;
|
reg cursor_on;
|
reg cursor_on;
|
wire cursor_on1;
|
wire cursor_on1;
|
reg video_on;
|
reg video_on;
|
wire video_on1;
|
wire video_on1;
|
|
|
// vga character ram access bus
|
// vga character ram access bus
|
reg [6:0] col_addr; // 0 to 79
|
reg [6:0] col_addr; // 0 to 79
|
reg [4:0] row_addr; // 0 to 49 (25 * 2 -1)
|
reg [4:0] row_addr; // 0 to 49 (25 * 2 -1)
|
reg [6:0] col1_addr; // 0 to 79
|
reg [6:0] col1_addr; // 0 to 79
|
reg [4:0] row1_addr; // 0 to 49 (25 * 2 - 1)
|
reg [4:0] row1_addr; // 0 to 49 (25 * 2 - 1)
|
reg [6:0] hor_addr; // 0 to 79
|
reg [6:0] hor_addr; // 0 to 79
|
reg [6:0] ver_addr; // 0 to 124
|
reg [6:0] ver_addr; // 0 to 124
|
reg vga0_we;
|
reg vga0_we;
|
reg vga0_rw, vga1_rw, vga2_rw, vga3_rw, vga4_rw;
|
reg vga0_rw, vga1_rw, vga2_rw, vga3_rw, vga4_rw, vga5_rw;
|
reg vga1_we;
|
reg vga1_we;
|
reg vga2_we;
|
reg vga2_we;
|
reg buff_we;
|
reg buff_we;
|
reg [7:0] buff_data_in;
|
reg [7:0] buff_data_in;
|
reg attr_we;
|
reg attr_we;
|
reg [7:0] attr_data_in;
|
reg [7:0] attr_data_in;
|
reg [10:0] buff_addr;
|
reg [10:0] buff_addr;
|
reg [10:0] attr0_addr;
|
reg [10:0] attr0_addr;
|
reg attr0_we;
|
reg attr0_we;
|
reg [10:0] buff0_addr;
|
reg [10:0] buff0_addr;
|
reg buff0_we;
|
reg buff0_we;
|
reg [10:0] attr_addr;
|
reg [10:0] attr_addr;
|
reg intense;
|
reg intense;
|
wire vga_cs;
|
wire vga_cs;
|
wire [7:0] vga_data_out;
|
wire [7:0] vga_data_out;
|
wire [7:0] attr_data_out;
|
wire [7:0] attr_data_out;
|
wire [10:0] vga_addr; // 2K byte character buffer
|
wire [10:0] vga_addr; // 2K byte character buffer
|
wire [15:0] out_data;
|
wire [15:0] out_data;
|
wire fg_or_bg;
|
wire fg_or_bg;
|
wire stb;
|
wire stb;
|
wire brown_bg;
|
wire brown_bg;
|
wire brown_fg;
|
wire brown_fg;
|
wire status_reg1;
|
wire status_reg1;
|
wire vh_retrace;
|
wire vh_retrace;
|
wire v_retrace;
|
wire v_retrace;
|
|
|
// Module instantiation
|
// Module instantiation
|
char_rom vdu_char_rom (
|
char_rom vdu_char_rom (
|
.clk (wb_clk_i),
|
.clk (wb_clk_i),
|
.rst (wb_rst_i),
|
.rst (wb_rst_i),
|
.cs (char_cs),
|
.cs (char_cs),
|
.we (char_we),
|
.we (char_we),
|
.addr (char_addr),
|
.addr (char_addr),
|
.wdata (char_data_in),
|
.wdata (char_data_in),
|
.rdata (char_data_out)
|
.rdata (char_data_out)
|
);
|
);
|
|
|
ram_2k char_buff_ram (
|
ram_2k char_buff_ram (
|
.clk (wb_clk_i),
|
.clk (wb_clk_i),
|
.rst (wb_rst_i),
|
.rst (wb_rst_i),
|
.cs (vga_cs),
|
.cs (vga_cs),
|
.we (buff_we),
|
.we (buff_we),
|
.addr (buff_addr),
|
.addr (buff_addr),
|
.wdata (buff_data_in),
|
.wdata (buff_data_in),
|
.rdata (vga_data_out)
|
.rdata (vga_data_out)
|
);
|
);
|
|
|
ram_2k_attr attr_buff_ram (
|
ram_2k_attr attr_buff_ram (
|
.clk (wb_clk_i),
|
.clk (wb_clk_i),
|
.rst (wb_rst_i),
|
.rst (wb_rst_i),
|
.cs (vga_cs),
|
.cs (vga_cs),
|
.we (attr_we),
|
.we (attr_we),
|
.addr (attr_addr),
|
.addr (attr_addr),
|
.wdata (attr_data_in),
|
.wdata (attr_data_in),
|
.rdata (attr_data_out)
|
.rdata (attr_data_out)
|
);
|
);
|
|
|
// Assignments
|
// Assignments
|
assign video_on1 = video_on_h && video_on_v;
|
assign video_on1 = video_on_h && video_on_v;
|
assign cursor_on1 = cursor_on_h && cursor_on_v;
|
assign cursor_on1 = cursor_on_h && cursor_on_v;
|
assign char_cs = 1'b1;
|
assign char_cs = 1'b1;
|
assign char_we = 1'b0;
|
assign char_we = 1'b0;
|
assign char_data_in = 8'b0;
|
assign char_data_in = 8'b0;
|
assign char_addr = { vga_data_out, v_count[3:0] };
|
assign char_addr = { vga_data_out, v_count[3:0] };
|
assign vga_addr = { 4'b0, hor_addr} + { ver_addr, 4'b0 };
|
assign vga_addr = { 4'b0, hor_addr} + { ver_addr, 4'b0 };
|
assign out_data = {attr_data_out, vga_data_out};
|
assign out_data = {attr_data_out, vga_data_out};
|
|
|
assign vga_cs = 1'b1;
|
assign vga_cs = 1'b1;
|
assign stb = wb_stb_i && wb_cyc_i;
|
assign stb = wb_stb_i && wb_cyc_i;
|
|
|
assign fg_or_bg = vga_shift[7] ^ cursor_on;
|
assign fg_or_bg = vga_shift[7] ^ cursor_on;
|
assign brown_fg = (vga_fg_colour==3'd6) && !intense;
|
assign brown_fg = (vga_fg_colour==3'd6) && !intense;
|
assign brown_bg = (vga_bg_colour==3'd6);
|
assign brown_bg = (vga_bg_colour==3'd6);
|
|
|
// Control registers
|
// Control registers
|
assign write = wb_tga_i & wb_stb_i & wb_cyc_i & wb_we_i;
|
assign write = wb_tga_i & wb_stb_i & wb_cyc_i & wb_we_i;
|
assign wr_adr = write & wb_sel_i[0];
|
assign wr_adr = write & wb_sel_i[0];
|
assign wr_reg = write & wb_sel_i[1];
|
assign wr_reg = write & wb_sel_i[1];
|
assign wr_hcursor = wr_reg & (reg_adr==4'hf);
|
assign wr_hcursor = wr_reg & (reg_adr==4'hf);
|
assign wr_vcursor = wr_reg & (reg_adr==4'he);
|
assign wr_vcursor = wr_reg & (reg_adr==4'he);
|
assign wr_cur_start = wr_reg & (reg_adr==4'ha);
|
assign wr_cur_start = wr_reg & (reg_adr==4'ha);
|
assign wr_cur_end = wr_reg & (reg_adr==4'hb);
|
assign wr_cur_end = wr_reg & (reg_adr==4'hb);
|
|
|
assign v_retrace = !video_on_v;
|
assign v_retrace = !video_on_v;
|
assign vh_retrace = v_retrace | !video_on_h;
|
assign vh_retrace = v_retrace | !video_on_h;
|
assign status_reg1 = { 11'b0, v_retrace, 3'b0, vh_retrace };
|
assign status_reg1 = { 11'b0, v_retrace, 3'b0, vh_retrace };
|
|
assign wb_ack_o = wb_tga_i ? stb : vga5_rw;
|
|
|
// Behaviour
|
// Behaviour
|
|
|
// CPU write interface
|
// CPU write interface
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
if (wb_rst_i)
|
if (wb_rst_i)
|
begin
|
begin
|
attr0_addr <= 11'b0;
|
attr0_addr <= 11'b0;
|
attr0_we <= 1'b0;
|
attr0_we <= 1'b0;
|
attr_data_in <= 8'h0;
|
attr_data_in <= 8'h0;
|
buff0_addr <= 11'b0;
|
buff0_addr <= 11'b0;
|
buff0_we <= 1'b0;
|
buff0_we <= 1'b0;
|
buff_data_in <= 8'h0;
|
buff_data_in <= 8'h0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (stb && !wb_tga_i)
|
if (stb && !wb_tga_i)
|
begin
|
begin
|
attr0_addr <= wb_adr_i;
|
attr0_addr <= wb_adr_i;
|
attr0_we <= wb_we_i & wb_sel_i[1];
|
attr0_we <= wb_we_i & wb_sel_i[1];
|
attr_data_in <= wb_dat_i[15:8];
|
attr_data_in <= wb_dat_i[15:8];
|
buff0_addr <= wb_adr_i;
|
buff0_addr <= wb_adr_i;
|
buff0_we <= wb_we_i & wb_sel_i[0];
|
buff0_we <= wb_we_i & wb_sel_i[0];
|
buff_data_in <= wb_dat_i[7:0];
|
buff_data_in <= wb_dat_i[7:0];
|
end
|
end
|
end
|
end
|
|
|
// CPU read interface
|
// CPU read interface
|
|
// wb_dat_o
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
if (wb_rst_i)
|
wb_dat_o <= wb_rst_i ? 16'h0 : (wb_tga_i ? status_reg1
|
begin
|
: (vga4_rw ? out_data : wb_dat_o));
|
wb_dat_o <= 16'h0;
|
|
wb_ack_o <= 16'h0;
|
|
end
|
|
else
|
|
if (wb_tga_i)
|
|
begin
|
|
wb_dat_o <= status_reg1;
|
|
wb_ack_o <= stb;
|
|
end
|
|
else
|
|
begin
|
|
wb_dat_o <= vga4_rw ? out_data : wb_dat_o;
|
|
wb_ack_o <= vga4_rw ? 1'b1 : (wb_ack_o && stb);
|
|
end
|
|
|
|
// Control registers
|
// Control registers
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
reg_adr <= wb_rst_i ? 4'h0
|
reg_adr <= wb_rst_i ? 4'h0
|
: (wr_adr ? wb_dat_i[3:0] : reg_adr);
|
: (wr_adr ? wb_dat_i[3:0] : reg_adr);
|
|
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
reg_hcursor <= wb_rst_i ? 7'h0
|
reg_hcursor <= wb_rst_i ? 7'h0
|
: (wr_hcursor ? wb_dat_i[14:8] : reg_hcursor);
|
: (wr_hcursor ? wb_dat_i[14:8] : reg_hcursor);
|
|
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
reg_vcursor <= wb_rst_i ? 5'h0
|
reg_vcursor <= wb_rst_i ? 5'h0
|
: (wr_vcursor ? wb_dat_i[12:8] : reg_vcursor);
|
: (wr_vcursor ? wb_dat_i[12:8] : reg_vcursor);
|
|
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
reg_cur_start <= wb_rst_i ? 4'he
|
reg_cur_start <= wb_rst_i ? 4'he
|
: (wr_cur_start ? wb_dat_i[11:8] : reg_cur_start);
|
: (wr_cur_start ? wb_dat_i[11:8] : reg_cur_start);
|
|
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
reg_cur_end <= wb_rst_i ? 4'hf
|
reg_cur_end <= wb_rst_i ? 4'hf
|
: (wr_cur_end ? wb_dat_i[11:8] : reg_cur_end);
|
: (wr_cur_end ? wb_dat_i[11:8] : reg_cur_end);
|
|
|
// Sync generation & timing process
|
// Sync generation & timing process
|
// Generate horizontal and vertical timing signals for video signal
|
// Generate horizontal and vertical timing signals for video signal
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
if (wb_rst_i)
|
if (wb_rst_i)
|
begin
|
begin
|
h_count <= 10'b0;
|
h_count <= 10'b0;
|
horiz_sync <= 1'b1;
|
horiz_sync <= 1'b1;
|
v_count <= 9'b0;
|
v_count <= 9'b0;
|
vert_sync <= 1'b1;
|
vert_sync <= 1'b1;
|
video_on_h <= 1'b1;
|
video_on_h <= 1'b1;
|
video_on_v <= 1'b1;
|
video_on_v <= 1'b1;
|
cursor_on_h <= 1'b0;
|
cursor_on_h <= 1'b0;
|
cursor_on_v <= 1'b0;
|
cursor_on_v <= 1'b0;
|
blink_count <= 22'b0;
|
blink_count <= 22'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
h_count <= (h_count==HOR_SCAN_END) ? 10'b0 : h_count + 10'b1;
|
h_count <= (h_count==HOR_SCAN_END) ? 10'b0 : h_count + 10'b1;
|
horiz_sync <= (h_count==HOR_SYNC_BEG) ? 1'b0
|
horiz_sync <= (h_count==HOR_SYNC_BEG) ? 1'b0
|
: ((h_count==HOR_SYNC_END) ? 1'b1 : horiz_sync);
|
: ((h_count==HOR_SYNC_END) ? 1'b1 : horiz_sync);
|
v_count <= (v_count==VER_SCAN_END && h_count==HOR_SCAN_END) ? 9'b0
|
v_count <= (v_count==VER_SCAN_END && h_count==HOR_SCAN_END) ? 9'b0
|
: ((h_count==HOR_SYNC_END) ? v_count + 9'b1 : v_count);
|
: ((h_count==HOR_SYNC_END) ? v_count + 9'b1 : v_count);
|
vert_sync <= (v_count==VER_SYNC_BEG) ? 1'b0
|
vert_sync <= (v_count==VER_SYNC_BEG) ? 1'b0
|
: ((v_count==VER_SYNC_END) ? 1'b1 : vert_sync);
|
: ((v_count==VER_SYNC_END) ? 1'b1 : vert_sync);
|
video_on_h <= (h_count==HOR_VIDEO_ON) ? 1'b1
|
video_on_h <= (h_count==HOR_VIDEO_ON) ? 1'b1
|
: ((h_count==HOR_VIDEO_OFF) ? 1'b0 : video_on_h);
|
: ((h_count==HOR_VIDEO_OFF) ? 1'b0 : video_on_h);
|
video_on_v <= (v_count==9'h0) ? 1'b1
|
video_on_v <= (v_count==9'h0) ? 1'b1
|
: ((v_count==VER_DISP_END) ? 1'b0 : video_on_v);
|
: ((v_count==VER_DISP_END) ? 1'b0 : video_on_v);
|
cursor_on_h <= (h_count[9:3] == reg_hcursor[6:0]);
|
cursor_on_h <= (h_count[9:3] == reg_hcursor[6:0]);
|
cursor_on_v <= (v_count[8:4] == reg_vcursor[4:0])
|
cursor_on_v <= (v_count[8:4] == reg_vcursor[4:0])
|
&& (v_count[3:0] >= reg_cur_start)
|
&& (v_count[3:0] >= reg_cur_start)
|
&& (v_count[3:0] <= reg_cur_end);
|
&& (v_count[3:0] <= reg_cur_end);
|
blink_count <= blink_count + 22'd1;
|
blink_count <= blink_count + 22'd1;
|
end
|
end
|
|
|
// Video memory access
|
// Video memory access
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
if (wb_rst_i)
|
if (wb_rst_i)
|
begin
|
begin
|
vga0_we <= 1'b0;
|
vga0_we <= 1'b0;
|
vga0_rw <= 1'b1;
|
vga0_rw <= 1'b1;
|
row_addr <= 5'b0;
|
row_addr <= 5'b0;
|
col_addr <= 7'b0;
|
col_addr <= 7'b0;
|
|
|
vga1_we <= 1'b0;
|
vga1_we <= 1'b0;
|
vga1_rw <= 1'b1;
|
vga1_rw <= 1'b1;
|
row1_addr <= 5'b0;
|
row1_addr <= 5'b0;
|
col1_addr <= 7'b0;
|
col1_addr <= 7'b0;
|
|
|
vga2_we <= 1'b0;
|
vga2_we <= 1'b0;
|
vga2_rw <= 1'b0;
|
vga2_rw <= 1'b0;
|
vga3_rw <= 1'b0;
|
vga3_rw <= 1'b0;
|
vga4_rw <= 1'b0;
|
vga4_rw <= 1'b0;
|
|
vga5_rw <= 1'b0;
|
ver_addr <= 7'b0;
|
ver_addr <= 7'b0;
|
hor_addr <= 7'b0;
|
hor_addr <= 7'b0;
|
|
|
buff_addr <= 10'b0;
|
buff_addr <= 10'b0;
|
attr_addr <= 10'b0;
|
attr_addr <= 10'b0;
|
buff_we <= 1'b0;
|
buff_we <= 1'b0;
|
attr_we <= 1'b0;
|
attr_we <= 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// on h_count = 0 initiate character write
|
// on h_count = 0 initiate character write
|
// all other cycles are reads
|
// all other cycles are reads
|
case (h_count[2:0])
|
case (h_count[2:0])
|
3'b000: // pipeline character write
|
3'b000: // pipeline character write
|
begin
|
begin
|
vga0_we <= wb_we_i;
|
vga0_we <= wb_we_i;
|
vga0_rw <= stb;
|
vga0_rw <= stb;
|
end
|
end
|
default: // other 6 cycles free
|
default: // other 6 cycles free
|
begin
|
begin
|
vga0_we <= 1'b0;
|
vga0_we <= 1'b0;
|
vga0_rw <= 1'b0;
|
vga0_rw <= 1'b0;
|
col_addr <= h_count[9:3];
|
col_addr <= h_count[9:3];
|
row_addr <= v_count[8:4];
|
row_addr <= v_count[8:4];
|
end
|
end
|
endcase
|
endcase
|
|
|
// on vdu_clk + 1 round off row address
|
// on vdu_clk + 1 round off row address
|
// row1_addr = (row_addr % 80)
|
// row1_addr = (row_addr % 80)
|
vga1_we <= vga0_we;
|
vga1_we <= vga0_we;
|
vga1_rw <= vga0_rw;
|
vga1_rw <= vga0_rw;
|
row1_addr <= (row_addr < VER_DISP_CHR) ? row_addr
|
row1_addr <= (row_addr < VER_DISP_CHR) ? row_addr
|
: row_addr - VER_DISP_CHR;
|
: row_addr - VER_DISP_CHR;
|
col1_addr <= col_addr;
|
col1_addr <= col_addr;
|
|
|
// on vdu_clk + 2 calculate vertical address
|
// on vdu_clk + 2 calculate vertical address
|
// ver_addr = (row_addr % 80) x 5
|
// ver_addr = (row_addr % 80) x 5
|
vga2_we <= vga1_we;
|
vga2_we <= vga1_we;
|
vga2_rw <= vga1_rw;
|
vga2_rw <= vga1_rw;
|
ver_addr <= { 2'b00, row1_addr } + { row1_addr, 2'b00 }; // x5
|
ver_addr <= { 2'b00, row1_addr } + { row1_addr, 2'b00 }; // x5
|
hor_addr <= col1_addr;
|
hor_addr <= col1_addr;
|
|
|
// on vdu_clk + 3 calculate memory address
|
// on vdu_clk + 3 calculate memory address
|
// vga_addr = (row_addr % 80) * 80 + hor_addr
|
// vga_addr = (row_addr % 80) * 80 + hor_addr
|
buff_addr <= vga2_rw ? buff0_addr : vga_addr;
|
buff_addr <= vga2_rw ? buff0_addr : vga_addr;
|
attr_addr <= vga2_rw ? attr0_addr : vga_addr;
|
attr_addr <= vga2_rw ? attr0_addr : vga_addr;
|
buff_we <= vga2_rw ? (buff0_we & vga2_we) : 1'b0;
|
buff_we <= vga2_rw ? (buff0_we & vga2_we) : 1'b0;
|
attr_we <= vga2_rw ? (attr0_we & vga2_we) : 1'b0;
|
attr_we <= vga2_rw ? (attr0_we & vga2_we) : 1'b0;
|
vga3_rw <= vga2_rw;
|
vga3_rw <= vga2_rw;
|
vga4_rw <= vga3_rw;
|
vga4_rw <= vga3_rw;
|
|
vga5_rw <= vga4_rw;
|
end
|
end
|
|
|
// Video shift register
|
// Video shift register
|
always @(posedge wb_clk_i)
|
always @(posedge wb_clk_i)
|
if (wb_rst_i)
|
if (wb_rst_i)
|
begin
|
begin
|
video_on <= 1'b0;
|
video_on <= 1'b0;
|
cursor_on <= 1'b0;
|
cursor_on <= 1'b0;
|
vga_bg_colour <= 3'b000;
|
vga_bg_colour <= 3'b000;
|
vga_fg_colour <= 3'b111;
|
vga_fg_colour <= 3'b111;
|
vga_shift <= 8'b00000000;
|
vga_shift <= 8'b00000000;
|
vga_red_o <= 1'b0;
|
vga_red_o <= 1'b0;
|
vga_green_o <= 1'b0;
|
vga_green_o <= 1'b0;
|
vga_blue_o <= 1'b0;
|
vga_blue_o <= 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (h_count[2:0] == 3'b000)
|
if (h_count[2:0] == 3'b000)
|
begin
|
begin
|
video_on <= video_on1;
|
video_on <= video_on1;
|
cursor_on <= (cursor_on1 | attr_data_out[7]) & blink_count[22];
|
cursor_on <= (cursor_on1 | attr_data_out[7]) & blink_count[22];
|
vga_fg_colour <= attr_data_out[2:0];
|
vga_fg_colour <= attr_data_out[2:0];
|
vga_bg_colour <= attr_data_out[6:4];
|
vga_bg_colour <= attr_data_out[6:4];
|
intense <= attr_data_out[3];
|
intense <= attr_data_out[3];
|
vga_shift <= char_data_out;
|
vga_shift <= char_data_out;
|
end
|
end
|
else vga_shift <= { vga_shift[6:0], 1'b0 };
|
else vga_shift <= { vga_shift[6:0], 1'b0 };
|
|
|
//
|
//
|
// Colour mask is
|
// Colour mask is
|
// 7 6 5 4 3 2 1 0
|
// 7 6 5 4 3 2 1 0
|
// X BR BG BB X FR FG FB
|
// X BR BG BB X FR FG FB
|
//
|
//
|
vga_blue_o <= video_on ? (fg_or_bg ? { vga_fg_colour[0], intense }
|
vga_blue_o <= video_on ? (fg_or_bg ? { vga_fg_colour[0], intense }
|
: { vga_bg_colour[0], 1'b0 })
|
: { vga_bg_colour[0], 1'b0 })
|
: 2'b0;
|
: 2'b0;
|
|
|
// Green color exception with color brown
|
// Green color exception with color brown
|
// http://en.wikipedia.org/wiki/Color_Graphics_Adapter#With_an_RGBI_monitor
|
// http://en.wikipedia.org/wiki/Color_Graphics_Adapter#With_an_RGBI_monitor
|
vga_green_o <= video_on ?
|
vga_green_o <= video_on ?
|
(fg_or_bg ? (brown_fg ? 2'b01 : { vga_fg_colour[1], intense })
|
(fg_or_bg ? (brown_fg ? 2'b01 : { vga_fg_colour[1], intense })
|
: (brown_bg ? 2'b01 : { vga_bg_colour[1], 1'b0 }))
|
: (brown_bg ? 2'b01 : { vga_bg_colour[1], 1'b0 }))
|
: 2'b0;
|
: 2'b0;
|
vga_red_o <= video_on ? (fg_or_bg ? { vga_fg_colour[2], intense }
|
vga_red_o <= video_on ? (fg_or_bg ? { vga_fg_colour[2], intense }
|
: { vga_bg_colour[2], 1'b0 })
|
: { vga_bg_colour[2], 1'b0 })
|
: 2'b0;
|
: 2'b0;
|
end
|
end
|
endmodule
|
endmodule
|
|
|