mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-05-02 22:43:41 +00:00
BBC: update the SDRAM controls and Teletext chip
This commit is contained in:
@@ -47,8 +47,8 @@ set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
|
||||
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
|
||||
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
|
||||
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)"
|
||||
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation
|
||||
set_global_assignment -name EDA_SIMULATION_TOOL "<None>"
|
||||
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
@@ -162,7 +162,6 @@ set_global_assignment -name PHYSICAL_SYNTHESIS_REGISTER_DUPLICATION ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_COMBO_LOGIC_FOR_AREA ON
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_MAP_LOGIC_TO_MEMORY_FOR_AREA ON
|
||||
set_location_assignment PLL_1 -to CLOCKS|altpll_component|auto_generated|pll1
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
set_global_assignment -name VERILOG_FILE ../rtl/sigma_delta_dac.v
|
||||
set_global_assignment -name VERILOG_FILE ../rtl/audio.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/adc.v
|
||||
@@ -174,8 +173,8 @@ set_global_assignment -name VERILOG_FILE ../../rtl/clocks.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/address_decode.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/bbc.v
|
||||
set_global_assignment -name VHDL_FILE ../../rtl/via6522.vhd
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/saa5050/saa5050_rom.v
|
||||
set_global_assignment -name VERILOG_FILE ../../rtl/saa5050/saa5050.v
|
||||
set_global_assignment -name VHDL_FILE ../../rtl/saa5050/saa5050_rom_dual_port.vhd
|
||||
set_global_assignment -name VHDL_FILE ../../rtl/saa5050/saa5050.vhd
|
||||
set_global_assignment -name VHDL_FILE "../../rtl/sn76489-1.0/sn76489_top.vhd"
|
||||
set_global_assignment -name VHDL_FILE "../../rtl/sn76489-1.0/sn76489_tone.vhd"
|
||||
set_global_assignment -name VHDL_FILE "../../rtl/sn76489-1.0/sn76489_noise.vhd"
|
||||
@@ -193,4 +192,5 @@ set_global_assignment -name VERILOG_FILE sdram.v
|
||||
set_global_assignment -name VERILOG_FILE clockgen.v
|
||||
set_global_assignment -name QIP_FILE "../../../../mist-modules/mist.qip"
|
||||
set_global_assignment -name VERILOG_FILE "../../../../mist-modules/sd_card.v"
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/via.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/via.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@@ -71,9 +71,6 @@ wire core_r, core_g, core_b, core_hs, core_vs;
|
||||
wire core_clken;
|
||||
|
||||
// memory bus signals.
|
||||
wire [14:0] vid_adr;
|
||||
wire [7:0] vid_data;
|
||||
|
||||
wire [15:0] mem_adr;
|
||||
wire [3:0] mem_romsel;
|
||||
|
||||
@@ -84,6 +81,7 @@ wire [7:0] ram_do;
|
||||
wire [7:0] mem_do;
|
||||
wire mem_we;
|
||||
wire mem_sync;
|
||||
wire phi0;
|
||||
|
||||
// core's raw audio
|
||||
wire [15:0] coreaud_l, coreaud_r;
|
||||
@@ -269,8 +267,8 @@ wire reset_in = ~pll_ready || ~sdram_ready || status[0] ||
|
||||
|
||||
// synchronize reset with memory state machine
|
||||
reg reset;
|
||||
always @(posedge mem_sync)
|
||||
reset <= reset_in;
|
||||
always @(posedge clk_32m)
|
||||
if (mem_sync) reset <= reset_in;
|
||||
|
||||
// the autoboot feature simply works by pressing shift for 2 seconds after
|
||||
// the bbc has been reset
|
||||
@@ -297,6 +295,7 @@ bbc BBC(
|
||||
.VIDEO_R ( core_r ),
|
||||
.VIDEO_G ( core_g ),
|
||||
.VIDEO_B ( core_b ),
|
||||
.VIDEO_DE ( video_de ),
|
||||
|
||||
.MEM_ADR ( mem_adr ),
|
||||
.MEM_WE ( mem_we ),
|
||||
@@ -304,9 +303,7 @@ bbc BBC(
|
||||
.MEM_DI ( mem_di ),
|
||||
.MEM_SYNC ( mem_sync ),
|
||||
.ROMSEL ( mem_romsel ),
|
||||
|
||||
.VID_ADR ( vid_adr ),
|
||||
.VID_DI ( vid_data ),
|
||||
.PHI0 ( phi0 ),
|
||||
|
||||
.SHIFT ( autoboot_shift ),
|
||||
|
||||
@@ -347,6 +344,8 @@ wire sdram_we = loader_active?loader_we:(mem_we && (cpu_ram || sideways_ram));
|
||||
wire [7:0] sdram_di =
|
||||
loader_active?loader_data:mem_do;
|
||||
|
||||
wire video_de;
|
||||
|
||||
sdram sdram (
|
||||
// interface to the MT48LC16M16 chip
|
||||
.sd_data ( SDRAM_DQ ),
|
||||
@@ -370,9 +369,7 @@ sdram sdram (
|
||||
.cpu_we ( sdram_we ),
|
||||
.cpu_do ( ram_do ),
|
||||
|
||||
.vid_blnk ( loader_active ),
|
||||
.vid_adr ( { 9'd0, vid_adr } ),
|
||||
.vid_do ( vid_data )
|
||||
.vid_blnk ( !video_de ) // for refresh
|
||||
);
|
||||
|
||||
wire [7:0] os_do;
|
||||
@@ -405,6 +402,7 @@ wire basic_map = rommap?(mem_romsel == 4'h0):(mem_romsel == 4'he);
|
||||
wire mmfs_map = rommap?(mem_romsel == 4'h2):(mem_romsel == 4'hc);
|
||||
|
||||
assign mem_di =
|
||||
~phi0 ? ram_do :
|
||||
((mem_adr[15:14] == 2'b10) && basic_map) ? basic_do :
|
||||
((mem_adr[15:14] == 2'b10) && mmfs_map) ? mmfs_do :
|
||||
((mem_adr[15:14] == 2'b10) && (mem_romsel == 4'ha)) ? ram_do :
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
module sdram (
|
||||
|
||||
// interface to the MT48LC16M16 chip
|
||||
inout [15:0] sd_data, // 16 bit bidirectional data bus
|
||||
output reg [12:0] sd_addr, // 13 bit multiplexed address bus
|
||||
output reg [1:0] sd_dqm, // two byte masks
|
||||
output reg[1:0] sd_ba, // two banks
|
||||
output sd_cs, // a single chip select
|
||||
output sd_we, // write enable
|
||||
output sd_ras, // row address select
|
||||
output sd_cas, // columns address select
|
||||
inout reg [15:0] sd_data, // 16 bit bidirectional data bus
|
||||
output reg [12:0] sd_addr, // 13 bit multiplexed address bus
|
||||
output reg [1:0] sd_dqm, // two byte masks
|
||||
output reg[1:0] sd_ba, // two banks
|
||||
output sd_cs, // a single chip select
|
||||
output sd_we, // write enable
|
||||
output sd_ras, // row address select
|
||||
output sd_cas, // columns address select
|
||||
|
||||
// cpu/chipset interface
|
||||
input init, // init signal after FPGA config to initialize RAM
|
||||
@@ -39,8 +39,6 @@ module sdram (
|
||||
output ready, // sdram is done initializing
|
||||
|
||||
input vid_blnk,
|
||||
input [24:0] vid_adr, // 24 bit video word address
|
||||
output reg [7:0] vid_do, // data output to video
|
||||
|
||||
input [7:0] cpu_di, // data input from cpu
|
||||
input [24:0] cpu_adr, // 24 bit cpu word address
|
||||
@@ -49,10 +47,10 @@ module sdram (
|
||||
);
|
||||
|
||||
// no burst configured
|
||||
localparam RASCAS_DELAY = 3'd2; // tRCD>=20ns -> 2 cycles@64MHz
|
||||
localparam RASCAS_DELAY = 3'd1; // tRCD>=20ns -> 1 cycle@32MHz
|
||||
localparam BURST_LENGTH = 3'b000; // 000=none, 001=2, 010=4, 011=8
|
||||
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
|
||||
localparam CAS_LATENCY = 3'd3; // 2/3 allowed
|
||||
localparam CAS_LATENCY = 3'd2; // 2/3 allowed
|
||||
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
|
||||
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
|
||||
|
||||
@@ -71,18 +69,18 @@ localparam STATE_LAST = 3'd7; // last state in cycle
|
||||
// itself to the cpu cycle. The first fill memory cycle is used for the CPU and the second
|
||||
// and fourth is used for video. The third cycle is refresh
|
||||
|
||||
reg [4:0] q;
|
||||
reg [3:0] q;
|
||||
always @(posedge clk) begin
|
||||
// 32Mhz counter synchronous to cpu
|
||||
if( sync ) q <= 5'd0;
|
||||
else q <= q + 5'd1;
|
||||
if( sync ) q <= 0;
|
||||
else q <= q + 1'd1;
|
||||
end
|
||||
|
||||
wire cpu_cyc = (q[4:3] == 2'b00);
|
||||
wire vid_cyc = (q[3] == 1'b1);
|
||||
wire cpu_cyc = q[3];
|
||||
wire vid_cyc = ~q[3];
|
||||
|
||||
// switch between video and cpu address
|
||||
wire [24:0] addr = vid_cyc?vid_adr:cpu_adr;
|
||||
wire [24:0] addr = cpu_adr;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// --------------------------- startup/reset ---------------------------
|
||||
@@ -122,24 +120,10 @@ assign sd_ras = sd_cmd[2];
|
||||
assign sd_cas = sd_cmd[1];
|
||||
assign sd_we = sd_cmd[0];
|
||||
|
||||
// drive data if it's the cpu cycle and if the cpu writes
|
||||
wire cpu_cycle_write = cpu_we && (q[4:3]==2'b00);
|
||||
assign sd_data = cpu_cycle_write?{cpu_di,cpu_di}:16'bZZZZZZZZZZZZZZZZ;
|
||||
|
||||
always @(posedge clk) begin
|
||||
// latch cpu data at the end of the cpu cycle
|
||||
if(cpu_cyc && (q[2:0] == 7) && !cpu_we)
|
||||
cpu_do <= cpu_adr[0]?sd_data[7:0]:sd_data[15:8];
|
||||
|
||||
// latch video data at end of video cycle
|
||||
if(vid_cyc && (q[2:0] == 7)) begin
|
||||
if(vid_blnk)
|
||||
vid_do = 8'h00;
|
||||
else
|
||||
vid_do <= vid_adr[0]?sd_data[7:0]:sd_data[15:8];
|
||||
end
|
||||
|
||||
sd_cmd <= CMD_INHIBIT;
|
||||
sd_data <= 16'bZZZZZZZZZZZZZZZZ;
|
||||
|
||||
if(reset != 0) begin
|
||||
sd_ba <= 2'b00;
|
||||
@@ -153,26 +137,32 @@ always @(posedge clk) begin
|
||||
if(reset == 2) sd_cmd <= CMD_LOAD_MODE;
|
||||
end
|
||||
end else begin
|
||||
if(q[2:0] <= STATE_CMD_START) begin
|
||||
sd_addr <= addr[21:9];
|
||||
sd_ba <= addr[23:22];
|
||||
sd_dqm <= { addr[0], !addr[0] };
|
||||
end else
|
||||
sd_addr <= { 4'b0010, addr[24], addr[8:1]};
|
||||
|
||||
|
||||
if(q[2:0] == STATE_IDLE) begin
|
||||
sd_cmd <= CMD_AUTO_REFRESH;
|
||||
|
||||
if(cpu_cyc || (vid_cyc)&&(!vid_blnk)) // CPU or video transfers data
|
||||
if(cpu_cyc || (vid_cyc && !vid_blnk)) begin// CPU or video transfers data
|
||||
sd_cmd <= CMD_ACTIVE;
|
||||
sd_addr <= addr[21:9];
|
||||
sd_ba <= addr[23:22];
|
||||
sd_dqm <= { addr[0], !addr[0] };
|
||||
end
|
||||
|
||||
end else if(q[2:0] == STATE_CMD_CONT) begin
|
||||
sd_addr <= { 4'b0010, addr[24], addr[8:1]};
|
||||
if(cpu_cyc) begin // CPU reads or writes
|
||||
if(cpu_we) sd_cmd <= CMD_WRITE;
|
||||
if(cpu_we) begin
|
||||
sd_cmd <= CMD_WRITE;
|
||||
sd_data <= {cpu_di,cpu_di};
|
||||
end
|
||||
else sd_cmd <= CMD_READ;
|
||||
end else if(vid_cyc && !vid_blnk) // video always reads
|
||||
sd_cmd <= CMD_READ;
|
||||
end
|
||||
end else if (q[2:0] == 5) begin
|
||||
cpu_do <= addr[0]?sd_data[7:0]:sd_data[15:8];
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -3,54 +3,52 @@
|
||||
module bbc(
|
||||
|
||||
input CLK32M_I,
|
||||
input CLK24M_I,
|
||||
|
||||
input RESET_I,
|
||||
|
||||
output HSYNC,
|
||||
output VSYNC,
|
||||
|
||||
output VIDEO_CLKEN,
|
||||
output VIDEO_R,
|
||||
output VIDEO_G,
|
||||
output VIDEO_B,
|
||||
|
||||
// RAM Interface (CPU)
|
||||
|
||||
output [15:0] MEM_ADR,
|
||||
output MEM_WE,
|
||||
output [7:0] MEM_DO,
|
||||
input [7:0] MEM_DI,
|
||||
output [3:0] ROMSEL,
|
||||
|
||||
output MEM_SYNC, // signal to synchronite sdram state machine
|
||||
|
||||
output [14:0] VID_ADR,
|
||||
input [7:0] VID_DI,
|
||||
|
||||
input CLK24M_I,
|
||||
|
||||
input RESET_I,
|
||||
|
||||
output HSYNC,
|
||||
output VSYNC,
|
||||
|
||||
output VIDEO_CLKEN,
|
||||
output VIDEO_R,
|
||||
output VIDEO_G,
|
||||
output VIDEO_B,
|
||||
output VIDEO_DE,
|
||||
|
||||
// RAM Interface (CPU)
|
||||
output [15:0] MEM_ADR,
|
||||
output MEM_WE,
|
||||
output [7:0] MEM_DO,
|
||||
input [7:0] MEM_DI,
|
||||
output [3:0] ROMSEL,
|
||||
|
||||
output MEM_SYNC, // signal to synchronite sdram state machine
|
||||
output PHI0,
|
||||
|
||||
// Keyboard interface
|
||||
input PS2_CLK,
|
||||
input PS2_DAT,
|
||||
|
||||
input PS2_CLK,
|
||||
input PS2_DAT,
|
||||
|
||||
// audio signal.
|
||||
output [15:0] AUDIO_L,
|
||||
output [15:0] AUDIO_R,
|
||||
|
||||
// externally pressed "shift" key for autoboot
|
||||
input SHIFT,
|
||||
input SHIFT,
|
||||
|
||||
output SDSS,
|
||||
output SDCLK,
|
||||
output SDMOSI,
|
||||
input SDMISO,
|
||||
|
||||
output SDSS,
|
||||
output SDCLK,
|
||||
output SDMOSI,
|
||||
input SDMISO,
|
||||
|
||||
// analog joystick input
|
||||
input [1:0] joy_but,
|
||||
input [7:0] joy0_axis0,
|
||||
input [7:0] joy0_axis1,
|
||||
input [7:0] joy1_axis0,
|
||||
input [7:0] joy1_axis1,
|
||||
|
||||
|
||||
// boot settings
|
||||
input [7:0] DIP_SWITCH
|
||||
);
|
||||
@@ -58,6 +56,8 @@ module bbc(
|
||||
// let sdram state machine synchronize to cpu
|
||||
assign MEM_SYNC = cpu_clken;
|
||||
assign ROMSEL = romsel;
|
||||
assign PHI0 = cpu_phi0;
|
||||
assign VIDEO_DE = crtc_de;
|
||||
|
||||
wire ram_we;
|
||||
|
||||
@@ -76,6 +76,7 @@ wire tube_clken;
|
||||
|
||||
wire cpu_clken;
|
||||
wire cpu_cycle;
|
||||
wire cpu_phi0;
|
||||
|
||||
// decode signals
|
||||
wire ddr_enable;
|
||||
@@ -248,6 +249,7 @@ clocks CLOCKS(
|
||||
|
||||
.cpu_cycle ( cpu_cycle ),
|
||||
.cpu_clken ( cpu_clken ),
|
||||
.cpu_phi0 ( cpu_phi0 ),
|
||||
|
||||
.ttxt_clken ( ttxt_clken ),
|
||||
.ttxt_clkenx2 ( ttxt_clkenx2 ),
|
||||
@@ -262,9 +264,9 @@ address_decode ADDRDECODE(
|
||||
.ram_enable(ram_enable),
|
||||
.rom_enable(rom_enable),
|
||||
.mos_enable(mos_enable),
|
||||
.io_fred(io_fred),
|
||||
.io_jim(io_jim),
|
||||
.io_sheila(io_sheila),
|
||||
.io_fred(io_fred),
|
||||
.io_jim(io_jim),
|
||||
.io_sheila(io_sheila),
|
||||
.crtc_enable(crtc_enable),
|
||||
.acia_enable(acia_enable),
|
||||
.serproc_enable(serproc_enable),
|
||||
@@ -290,7 +292,7 @@ T65 CPU (
|
||||
.IRQ_n (cpu_irq_n),
|
||||
.SO_n (cpu_so_n),
|
||||
.R_W_n (cpu_r_nw),
|
||||
|
||||
|
||||
.DI (cpu_di),
|
||||
.DO (cpu_do),
|
||||
.A (cpu_a)
|
||||
@@ -412,7 +414,6 @@ adc ADC (
|
||||
mc6845 CRTC (
|
||||
.CLOCK(CLK32M_I),
|
||||
.CLKEN(crtc_clken),
|
||||
.CLKEN_ADR(crtc_clken_adr),
|
||||
.nRESET(reset_n),
|
||||
.ENABLE(crtc_enable),
|
||||
.R_nW(cpu_r_nw),
|
||||
@@ -449,11 +450,10 @@ vidproc VIDEO_ULA (
|
||||
.CLKEN(VIDEO_CLKEN),
|
||||
.nRESET(reset_n),
|
||||
.CLKEN_CRTC(crtc_clken),
|
||||
.CLKEN_CRTC_ADR(crtc_clken_adr),
|
||||
.ENABLE(vidproc_enable),
|
||||
.A0(cpu_a[0]),
|
||||
.DI_CPU(cpu_do),
|
||||
.DI_RAM(VID_DI[7:0]),
|
||||
.DI_RAM(MEM_DI[7:0]),
|
||||
.nINVERT(vidproc_invert_n),
|
||||
.DISEN(vidproc_disen),
|
||||
.CURSOR(crtc_cursor),
|
||||
@@ -469,26 +469,24 @@ vidproc VIDEO_ULA (
|
||||
|
||||
saa5050 TELETEXT (
|
||||
|
||||
// This runs at 6 MHz, which we can't derive from the 32 MHz clock
|
||||
.CLOCK ( CLK24M_I ),
|
||||
.CLKEN ( ttxt_clken ),
|
||||
.PIXCLKEN ( ttxt_clkenx2 ),
|
||||
.nRESET ( reset_n ),
|
||||
|
||||
// Data input is synchronised to the main cpu bus clock.
|
||||
.DI_CLOCK ( CLK32M_I ),
|
||||
.DI_CLKEN ( VIDEO_CLKEN ),
|
||||
.DI ( VID_DI[6:0] ),
|
||||
|
||||
.GLR ( ttxt_glr ),
|
||||
.DEW ( ttxt_dew ),
|
||||
.CRS ( ttxt_crs ),
|
||||
.LOSE ( ttxt_lose ),
|
||||
|
||||
.R ( ttxt_r ),
|
||||
.G ( ttxt_g ),
|
||||
.B ( ttxt_b )
|
||||
// This runs at 6 MHz, which we can't derive from the 32 MHz clock
|
||||
.CLOCK ( CLK24M_I ),
|
||||
.CLKEN ( ttxt_clkenx2 ),
|
||||
.nRESET ( reset_n ),
|
||||
|
||||
// Data input is synchronised to the main cpu bus clock.
|
||||
.DI_CLOCK ( CLK32M_I ),
|
||||
.DI_CLKEN ( VIDEO_CLKEN & mhz4_clken & ~mhz2_clken ),
|
||||
.DI ( MEM_DI[6:0] ),
|
||||
|
||||
.GLR ( ttxt_glr ),
|
||||
.DEW ( ttxt_dew ),
|
||||
.CRS ( ttxt_crs ),
|
||||
.LOSE ( ttxt_lose ),
|
||||
|
||||
.R ( ttxt_r ),
|
||||
.G ( ttxt_g ),
|
||||
.B ( ttxt_b )
|
||||
);
|
||||
|
||||
initial begin : via_init
|
||||
@@ -655,11 +653,8 @@ assign sys_via_pb_in[3:0] = sys_via_pb_out[3:0];
|
||||
assign user_via_pa_in = user_via_pa_out;
|
||||
assign user_via_pb_in = user_via_pb_out;
|
||||
|
||||
|
||||
|
||||
assign MEM_ADR = cpu_a[15:0];
|
||||
assign VID_ADR = display_a;
|
||||
assign MEM_WE = ram_we;
|
||||
assign MEM_ADR = cpu_phi0 ? cpu_a[15:0] : display_a;
|
||||
assign MEM_WE = ram_we & cpu_phi0;
|
||||
assign MEM_DO = cpu_do;
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -39,6 +39,7 @@ module clocks(
|
||||
|
||||
output wire cpu_cycle,
|
||||
output wire cpu_clken,
|
||||
output wire cpu_phi0,
|
||||
|
||||
output wire vid_clken,
|
||||
output wire ttxt_clken,
|
||||
@@ -71,6 +72,9 @@ assign cpu_cycle = ~(clken_counter[0] | clken_counter[1] | clken_counter[2] | cl
|
||||
// 0/16^M
|
||||
assign cpu_clken = cpu_cycle & ~cpu_cycle_mask[1] & ~cpu_cycle_mask[0];
|
||||
|
||||
wire [4:0] clken_counter_next = clken_counter - 1'd1;
|
||||
assign cpu_phi0 = clken_counter_next[3];
|
||||
|
||||
always @(posedge clk_32m)
|
||||
begin : clk_gen
|
||||
// if (reset_n === 1'b 0)
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
module mc6845 (
|
||||
CLOCK,
|
||||
CLKEN,
|
||||
CLKEN_ADR,
|
||||
nRESET,
|
||||
ENABLE,
|
||||
R_nW,
|
||||
@@ -67,7 +66,6 @@ module mc6845 (
|
||||
|
||||
input CLOCK;
|
||||
input CLKEN;
|
||||
input CLKEN_ADR;
|
||||
input nRESET;
|
||||
input ENABLE;
|
||||
input R_nW;
|
||||
@@ -537,7 +535,7 @@ always @(posedge CLOCK) begin
|
||||
RA <= 'd0;
|
||||
MA <= 'd0;
|
||||
end
|
||||
else if (CLKEN_ADR === 1'b 1 ) begin
|
||||
else if (CLKEN === 1'b 1 ) begin
|
||||
|
||||
// Character row address is just the scan line counter delayed by
|
||||
// one clock to line up with the syncs.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,455 +0,0 @@
|
||||
// SAA5050 teletext generator
|
||||
//
|
||||
// Synchronous implementation for FPGA. Certain TV-specific functions are
|
||||
// not implemented. e.g.
|
||||
//
|
||||
// No /SI pin - 'TEXT' mode is permanently enabled
|
||||
// No remote control features (/DATA, DLIM)
|
||||
// No large character support
|
||||
// No support for box overlay (BLAN, PO, DE)
|
||||
//
|
||||
// FIXME: Hold graphics not supported - this needs to be added
|
||||
//
|
||||
// Copyright (c) 2011 Mike Stirling
|
||||
// Copyright (c) 2015 Stephen J. Leary (sleary@vavi.co.uk)
|
||||
//
|
||||
// All rights reserved
|
||||
//
|
||||
// Redistribution and use in source and synthezised forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in synthesized form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software without
|
||||
// specific prior written agreement from the author.
|
||||
//
|
||||
// * License is granted for non-commercial use only. A fee may not be charged
|
||||
// for redistributions as source code or in synthesized/hardware form without
|
||||
// specific prior written agreement from the author.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
module saa5050 (
|
||||
CLOCK,
|
||||
CLKEN,
|
||||
PIXCLKEN,
|
||||
nRESET,
|
||||
DI_CLOCK,
|
||||
DI_CLKEN,
|
||||
DI,
|
||||
GLR,
|
||||
DEW,
|
||||
CRS,
|
||||
LOSE,
|
||||
R,
|
||||
G,
|
||||
B,
|
||||
Y);
|
||||
|
||||
|
||||
input CLOCK;
|
||||
input CLKEN;
|
||||
input PIXCLKEN;
|
||||
input nRESET;
|
||||
input DI_CLOCK;
|
||||
input DI_CLKEN;
|
||||
input [6: 0] DI;
|
||||
input GLR;
|
||||
input DEW;
|
||||
input CRS;
|
||||
input LOSE;
|
||||
output R;
|
||||
output G;
|
||||
output B;
|
||||
output Y;
|
||||
|
||||
// 6 MHz dot clock enable
|
||||
|
||||
reg R;
|
||||
reg G;
|
||||
reg B;
|
||||
reg Y;
|
||||
|
||||
// Register inputs in the bus clock domain
|
||||
reg [6: 0] di_r;
|
||||
reg dew_r;
|
||||
reg lose_r;
|
||||
|
||||
// Data input registered in the pixel clock domain
|
||||
reg [6: 0] code;
|
||||
wire [3: 0] line_addr;
|
||||
wire [11: 0] rom_address;
|
||||
wire [7: 0] rom_data;
|
||||
wire [3:0] line_addr_cmp;
|
||||
wire [3:0] line_addr_p1;
|
||||
wire [3:0] line_addr_m1;
|
||||
wire [11:0] rom_address_cmp;
|
||||
wire [7:0] rom_data_cmp;
|
||||
// Delayed display enable derived from LOSE by delaying for one character
|
||||
reg disp_enable;
|
||||
|
||||
// Latched timing signals for detection of falling edges
|
||||
reg dew_latch;
|
||||
reg lose_latch;
|
||||
reg disp_enable_latch;
|
||||
|
||||
// Row and column addressing is handled externally. We just need to
|
||||
// keep track of which of the 10 lines we are on within the character...
|
||||
reg [3: 0] line_counter;
|
||||
|
||||
// ... and which of the 6 pixels we are on within each line
|
||||
reg [2: 0] pixel_counter;
|
||||
|
||||
// We also need to count frames to implement the flash feature.
|
||||
// The datasheet says this is 0.75 Hz with a 3:1 on/off ratio, so it
|
||||
// is probably a /64 counter, which gives us 0.78 Hz
|
||||
reg [5: 0] flash_counter;
|
||||
|
||||
// Output shift register
|
||||
reg odd_pixel;
|
||||
reg shift_reg_last;
|
||||
reg [5: 0] shift_reg;
|
||||
reg shift_reg_cmp_last;
|
||||
reg [5:0] shift_reg_cmp;
|
||||
|
||||
// Flash mask
|
||||
wire flash;
|
||||
|
||||
// Current display state
|
||||
// Foreground colour (B2, G1, R0)
|
||||
reg [2: 0] fg;
|
||||
|
||||
// Background colour (B2, G1, R0)
|
||||
reg [2: 0] bg;
|
||||
reg conceal;
|
||||
reg gfx;
|
||||
reg gfx_sep;
|
||||
reg gfx_hold;
|
||||
reg is_flash;
|
||||
reg double_high;
|
||||
|
||||
// Set in first row of double height
|
||||
reg double_high1;
|
||||
|
||||
// Set in second row of double height
|
||||
reg double_high2;
|
||||
|
||||
saa5050_rom char_rom (.address(rom_address),
|
||||
.clock(CLOCK),
|
||||
.q(rom_data));
|
||||
assign flash = flash_counter[5] & flash_counter[4];
|
||||
// Generate flash signal for 3:1 ratio
|
||||
// Sync inputs
|
||||
|
||||
always @(posedge DI_CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
di_r <= {7{1'b 0}};
|
||||
dew_r <= 1'b 0;
|
||||
lose_r <= 1'b 0;
|
||||
|
||||
end else if (DI_CLKEN === 1'b 1 ) begin
|
||||
di_r <= DI;
|
||||
dew_r <= DEW;
|
||||
lose_r <= LOSE;
|
||||
end
|
||||
end
|
||||
|
||||
// Register data into pixel clock domain
|
||||
|
||||
always @(posedge CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
code <= {7{1'b 0}};
|
||||
|
||||
end else if (CLKEN === 1'b 1 ) begin
|
||||
code <= di_r;
|
||||
end
|
||||
end
|
||||
|
||||
// Generate character rom address in pixel clock domain
|
||||
// This is done combinatorially since all the inputs are already
|
||||
// registered and the address is re-registered by the ROM
|
||||
assign line_addr = double_high === 1'b 0 ? line_counter :
|
||||
double_high2 === 1'b 0 ? {1'b 0, line_counter[3 : 1]} :
|
||||
{1'b 0, line_counter[3 : 1]} + 4'd5;
|
||||
assign rom_address = double_high === 1'b 0 & double_high2 === 1'b 1 ? {12{1'b 0}} :
|
||||
{gfx, code, line_addr};
|
||||
assign line_addr_p1 = double_high === 1'b 0 ? line_counter + 1 :
|
||||
double_high2 === 1'b 0 ? {1'b 0, line_counter[3:1]} + 1 :
|
||||
{1'b 0, line_counter[3:1]} + 1 + 5;
|
||||
assign line_addr_m1 = double_high === 1'b 0 ? line_counter - 1 :
|
||||
double_high2 === 1'b 0 ? {1'b 0, line_counter[3:1]} - 1 :
|
||||
{1'b 0, line_counter[3:1]} - 1 + 5;
|
||||
assign line_addr_cmp = CRS === 1'b 1 ? line_addr_p1 :
|
||||
line_addr_m1;
|
||||
assign rom_address_cmp = double_high === 1'b 0 & double_high2 === 1'b 1 ? {12{1'b 0}} :
|
||||
{gfx, code, line_addr_cmp};
|
||||
|
||||
// Character row and pixel counters
|
||||
|
||||
always @(posedge CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
dew_latch <= 1'b 0;
|
||||
lose_latch <= 1'b 0;
|
||||
disp_enable <= 1'b 0;
|
||||
disp_enable_latch <= 1'b 0;
|
||||
double_high1 <= 1'b 0;
|
||||
double_high2 <= 1'b 0;
|
||||
line_counter <= {4{1'b 0}};
|
||||
pixel_counter <= {3{1'b 0}};
|
||||
flash_counter <= {6{1'b 0}};
|
||||
|
||||
end else if (CLKEN === 1'b 1 ) begin
|
||||
|
||||
// Register syncs for edge detection
|
||||
dew_latch <= dew_r;
|
||||
lose_latch <= lose_r;
|
||||
disp_enable_latch <= disp_enable;
|
||||
|
||||
// When first entering double-height mode start on top row
|
||||
if (double_high === 1'b 1 & double_high1 === 1'b 0 &
|
||||
double_high2 === 1'b 0) begin
|
||||
double_high1 <= 1'b 1;
|
||||
end
|
||||
|
||||
// Count pixels between 0 and 5
|
||||
if (pixel_counter === 5) begin
|
||||
|
||||
// Start of next character and delayed display enable
|
||||
pixel_counter <= {3{1'b 0}};
|
||||
disp_enable <= lose_latch;
|
||||
|
||||
end else begin
|
||||
pixel_counter <= pixel_counter + 1;
|
||||
end
|
||||
|
||||
// Rising edge of LOSE is the start of the active line
|
||||
if (lose_r === 1'b 1 & lose_latch === 1'b 0) begin
|
||||
|
||||
// Reset pixel counter - small offset to make the output
|
||||
// line up with the cursor from the video ULA
|
||||
pixel_counter <= 3'b 011;
|
||||
end
|
||||
|
||||
// Count frames on end of VSYNC (falling edge of DEW)
|
||||
if (dew_r === 1'b 0 & dew_latch === 1'b 1) begin
|
||||
flash_counter <= flash_counter + 1;
|
||||
end
|
||||
|
||||
if (dew_r === 1'b 1) begin
|
||||
|
||||
// Reset line counter and double height state during VSYNC
|
||||
line_counter <= {4{1'b 0}};
|
||||
double_high1 <= 1'b 0;
|
||||
double_high2 <= 1'b 0;
|
||||
|
||||
// Count lines on end of active video (falling edge of disp_enable)
|
||||
|
||||
end else begin
|
||||
if (disp_enable === 1'b 0 & disp_enable_latch === 1'b 1) begin
|
||||
if (line_counter === 9) begin
|
||||
line_counter <= {4{1'b 0}};
|
||||
|
||||
// Keep track of which row we are on for double-height
|
||||
// The double_high flag can be cleared before the end of a row, but if
|
||||
// double height characters are used anywhere on a row then the double_high1
|
||||
// flag will be set and remain set until the next row. This is used
|
||||
// to determine that the bottom half of the characters should be shown if
|
||||
// double_high is set once again on the row below.
|
||||
double_high1 <= 1'b 0;
|
||||
double_high2 <= double_high1;
|
||||
end
|
||||
else begin
|
||||
line_counter <= line_counter + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Shift register
|
||||
|
||||
always @(posedge CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
|
||||
shift_reg <= {6{1'b 0}};
|
||||
|
||||
end else if (CLKEN === 1'b 1 ) begin
|
||||
|
||||
if (disp_enable === 1'b 1 & pixel_counter === 0) begin
|
||||
|
||||
// Load the shift register with the ROM bit pattern
|
||||
// at the start of each character while disp_enable is asserted.
|
||||
shift_reg <= rom_data[5: 0];
|
||||
shift_reg_cmp <= rom_data_cmp[5:0];
|
||||
|
||||
// If bit 7 of the ROM data is set then this is a graphics
|
||||
// character and separated/hold graphics modes apply.
|
||||
// We don't just assume this to be the case if gfx=1 because
|
||||
// these modes don't apply to caps even in graphics mode
|
||||
if (rom_data[7] === 1'b 1) begin
|
||||
|
||||
// Apply a mask for separated graphics mode
|
||||
if (gfx_sep === 1'b 1) begin
|
||||
shift_reg[5] <= 1'b 0;
|
||||
shift_reg[2] <= 1'b 0;
|
||||
|
||||
if (line_counter === 2 | line_counter === 6 |
|
||||
line_counter === 9) begin
|
||||
shift_reg <= {6{1'b 0}};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (rom_data_cmp[7] === 1'b 1) begin
|
||||
|
||||
// Apply a mask for separated graphics mode
|
||||
if (gfx_sep === 1'b 1) begin
|
||||
shift_reg_cmp[5] <= 1'b 0;
|
||||
shift_reg_cmp[2] <= 1'b 0;
|
||||
|
||||
if (line_counter === 1 | line_counter === 5 |
|
||||
line_counter === 8) begin
|
||||
shift_reg_cmp <= {6{1'b 0}};
|
||||
end
|
||||
end
|
||||
end // Pump the shift register
|
||||
end else begin
|
||||
shift_reg_last <= shift_reg[5];
|
||||
shift_reg <= {shift_reg[4: 0], 1'b 0};
|
||||
shift_reg_cmp_last <= shift_reg_cmp[5];
|
||||
shift_reg_cmp <= {shift_reg_cmp[4:0], 1'b 0};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Control character handling
|
||||
|
||||
always @(posedge CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
fg <= {3{1'b 1}};
|
||||
bg <= {3{1'b 0}};
|
||||
conceal <= 1'b 0;
|
||||
gfx <= 1'b 0;
|
||||
gfx_sep <= 1'b 0;
|
||||
gfx_hold <= 1'b 0;
|
||||
is_flash <= 1'b 0;
|
||||
double_high <= 1'b 0;
|
||||
|
||||
end else if (CLKEN === 1'b 1 ) begin
|
||||
|
||||
if (disp_enable === 1'b 0) begin
|
||||
|
||||
// Reset to start of line defaults
|
||||
fg <= 3'b111;
|
||||
bg <= 'd0;
|
||||
conceal <= 1'b 0;
|
||||
gfx <= 1'b 0;
|
||||
gfx_sep <= 1'b 0;
|
||||
gfx_hold <= 1'b 0;
|
||||
is_flash <= 1'b 0;
|
||||
double_high <= 1'b 0;
|
||||
|
||||
end else if (pixel_counter === 0 ) begin
|
||||
|
||||
// Latch new control codes at the start of each character
|
||||
if (code[6: 5] === 2'b 00) begin
|
||||
|
||||
if (code[3] === 1'b 0) begin
|
||||
|
||||
// Colour and graphics setting clears conceal mode
|
||||
conceal <= 1'b 0;
|
||||
|
||||
// Select graphics or alpha mode
|
||||
gfx <= code[4];
|
||||
|
||||
// 0 would be black but is not allowed so has no effect,
|
||||
// otherwise set the colour
|
||||
if (code[2: 0] !== 3'b 000) begin
|
||||
fg <= code[2: 0];
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
case (code[4: 0])
|
||||
|
||||
5'b 01000: is_flash <= 1'b1; // FLASH
|
||||
5'b 01001: is_flash <= 1'b0; // STEADY
|
||||
5'b 01100: double_high <= 1'b0; // NORMAL HEIGHT
|
||||
5'b 01101: double_high <= 1'b1; // DOUBLE HEIGHT
|
||||
5'b 11000: conceal <= 1'b1; // CONCEAL
|
||||
5'b 11001: gfx_sep <= 1'b0; // CONTIGUOUS GFX
|
||||
5'b 11010: gfx_sep <= 1'b1; // SEPARATED GFX
|
||||
5'b 11100: bg <= 'd0; // BLACK BACKGROUND
|
||||
5'b 11101: bg <= fg; // NEW BACKGROUND
|
||||
5'b 11110: gfx_hold <= 1'b1; // HOLD GFX
|
||||
5'b 11111: gfx_hold <= 1'b0; // RELEASE GFX
|
||||
|
||||
endcase
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Output pixel calculation.
|
||||
wire pixel = double_high === 1'b 1 ? shift_reg[5] & ~(flash & is_flash | conceal) :
|
||||
odd_pixel === 1'b 0 ? (shift_reg[5] | shift_reg_cmp[5] & shift_reg[4] & ~shift_reg_cmp[4]) & ~(flash & is_flash | conceal) :
|
||||
(shift_reg[5] | shift_reg_cmp[5] & shift_reg_last & ~shift_reg_cmp_last) & ~(flash & is_flash | conceal);
|
||||
|
||||
always @(posedge CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
|
||||
R <= 1'b 0;
|
||||
G <= 1'b 0;
|
||||
B <= 1'b 0;
|
||||
|
||||
end else if (PIXCLKEN === 1'b 1 ) begin
|
||||
|
||||
// Generate mono output
|
||||
Y <= pixel;
|
||||
odd_pixel <= ~odd_pixel;
|
||||
|
||||
// Generate colour output
|
||||
if (pixel === 1'b 1) begin
|
||||
|
||||
R <= fg[0];
|
||||
G <= fg[1];
|
||||
B <= fg[2];
|
||||
|
||||
end else begin
|
||||
|
||||
R <= bg[0];
|
||||
G <= bg[1];
|
||||
B <= bg[2];
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endmodule // module saa5050
|
||||
|
||||
582
cores/bbc/rtl/saa5050/saa5050.vhd
Normal file
582
cores/bbc/rtl/saa5050/saa5050.vhd
Normal file
@@ -0,0 +1,582 @@
|
||||
-- BBC Micro for Altera DE1
|
||||
--
|
||||
-- Copyright (c) 2011 Mike Stirling
|
||||
--
|
||||
-- All rights reserved
|
||||
--
|
||||
-- Redistribution and use in source and synthezised forms, with or without
|
||||
-- modification, are permitted provided that the following conditions are met:
|
||||
--
|
||||
-- * Redistributions of source code must retain the above copyright notice,
|
||||
-- this list of conditions and the following disclaimer.
|
||||
--
|
||||
-- * Redistributions in synthesized form must reproduce the above copyright
|
||||
-- notice, this list of conditions and the following disclaimer in the
|
||||
-- documentation and/or other materials provided with the distribution.
|
||||
--
|
||||
-- * Neither the name of the author nor the names of other contributors may
|
||||
-- be used to endorse or promote products derived from this software without
|
||||
-- specific prior written agreement from the author.
|
||||
--
|
||||
-- * License is granted for non-commercial use only. A fee may not be charged
|
||||
-- for redistributions as source code or in synthesized/hardware form without
|
||||
-- specific prior written agreement from the author.
|
||||
--
|
||||
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
-- POSSIBILITY OF SUCH DAMAGE.
|
||||
--
|
||||
-- SAA5050 teletext generator
|
||||
--
|
||||
-- Synchronous implementation for FPGA. Certain TV-specific functions are
|
||||
-- not implemented. e.g.
|
||||
--
|
||||
-- No /SI pin - 'TEXT' mode is permanently enabled
|
||||
-- No remote control features (/DATA, DLIM)
|
||||
-- No large character support
|
||||
-- No support for box overlay (BLAN, PO, DE)
|
||||
--
|
||||
--
|
||||
--
|
||||
-- (C) 2011 Mike Stirling
|
||||
--
|
||||
-- Updated to run at 12MHz rather than 6MHz
|
||||
-- Character rounding added
|
||||
-- Implemented Graphics Hold
|
||||
-- Lots of fixes to correctly implement Set-At and Set-After control codes
|
||||
--
|
||||
-- (C) 2015 David Banks
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity saa5050 is
|
||||
port (
|
||||
CLOCK : in std_logic;
|
||||
-- 6 MHz dot clock enable
|
||||
CLKEN : in std_logic;
|
||||
-- Async reset
|
||||
nRESET : in std_logic;
|
||||
|
||||
-- Indicates special VGA Mode 7 (720x576p)
|
||||
VGA : in std_logic;
|
||||
|
||||
-- Character data input (in the bus clock domain)
|
||||
DI_CLOCK : in std_logic;
|
||||
DI_CLKEN : in std_logic;
|
||||
DI : in std_logic_vector(6 downto 0);
|
||||
|
||||
-- Timing inputs
|
||||
-- General line reset (not used)
|
||||
GLR : in std_logic; -- /HSYNC
|
||||
-- Data entry window - high during VSYNC.
|
||||
-- Resets ROM row counter and drives 'flash' signal
|
||||
DEW : in std_logic; -- VSYNC
|
||||
-- Character rounding select - high during even field
|
||||
CRS : in std_logic; -- FIELD
|
||||
-- Load output shift register enable - high during active video
|
||||
LOSE : in std_logic; -- DE
|
||||
|
||||
-- Video out
|
||||
R : out std_logic;
|
||||
G : out std_logic;
|
||||
B : out std_logic;
|
||||
Y : out std_logic
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture rtl of saa5050 is
|
||||
|
||||
-- Register inputs in the bus clock domain
|
||||
signal di_r : std_logic_vector(6 downto 0);
|
||||
signal dew_r : std_logic;
|
||||
signal lose_r : std_logic;
|
||||
-- Data input registered in the pixel clock domain
|
||||
signal code : std_logic_vector(6 downto 0);
|
||||
signal line_addr : unsigned(3 downto 0);
|
||||
signal rom_address1 : std_logic_vector(11 downto 0);
|
||||
signal rom_address2 : std_logic_vector(11 downto 0);
|
||||
signal rom_data1 : std_logic_vector(7 downto 0);
|
||||
signal rom_data2 : std_logic_vector(7 downto 0);
|
||||
|
||||
-- Delayed display enable derived from LOSE by delaying for one and two characters
|
||||
signal disp_enable : std_logic;
|
||||
-- Latched timing signals for detection of falling edges
|
||||
signal dew_latch : std_logic;
|
||||
signal lose_latch : std_logic;
|
||||
signal disp_enable_latch : std_logic;
|
||||
|
||||
-- Row and column addressing is handled externally. We just need to
|
||||
-- keep track of which of the 10 lines we are on within the character...
|
||||
signal line_counter : unsigned(3 downto 0);
|
||||
-- ... and which of the 12 pixels we are on within each line
|
||||
signal pixel_counter : unsigned(3 downto 0);
|
||||
-- We also need to count frames to implement the flash feature.
|
||||
-- The datasheet says this is 0.75 Hz with a 3:1 on/off ratio, so it
|
||||
-- is probably a /64 counter, which gives us 0.78 Hz
|
||||
signal flash_counter : unsigned(5 downto 0);
|
||||
-- Output shift register
|
||||
signal shift_reg : std_logic_vector(11 downto 0);
|
||||
|
||||
-- Flash mask
|
||||
signal flash : std_logic;
|
||||
|
||||
-- Current display state
|
||||
-- Foreground colour (B2, G1, R0)
|
||||
signal fg : std_logic_vector(2 downto 0);
|
||||
-- Background colour (B2, G1, R0)
|
||||
signal bg : std_logic_vector(2 downto 0);
|
||||
signal conceal : std_logic;
|
||||
signal gfx : std_logic;
|
||||
signal gfx_sep : std_logic;
|
||||
signal gfx_hold : std_logic;
|
||||
signal is_flash : std_logic;
|
||||
signal double_high : std_logic;
|
||||
|
||||
-- One-shot versions of certain control signals to support "Set-After" semantics
|
||||
signal fg_next : std_logic_vector(2 downto 0);
|
||||
signal alpha_next : std_logic;
|
||||
signal gfx_next : std_logic;
|
||||
signal gfx_release_next : std_logic;
|
||||
signal is_flash_next : std_logic;
|
||||
signal double_high_next : std_logic;
|
||||
signal unconceal_next : std_logic;
|
||||
|
||||
-- Once char delayed versions of all of the signals seen by the ROM/Shift Register/Output Stage
|
||||
-- This is to compensate for the one char delay through the control state machine
|
||||
signal code_r : std_logic_vector(6 downto 0);
|
||||
signal disp_enable_r: std_logic;
|
||||
signal fg_r : std_logic_vector(2 downto 0);
|
||||
signal bg_r : std_logic_vector(2 downto 0);
|
||||
signal conceal_r : std_logic;
|
||||
signal is_flash_r : std_logic;
|
||||
|
||||
-- Last graphics character, for use by graphics hold
|
||||
signal last_gfx_sep : std_logic;
|
||||
signal last_gfx : std_logic_vector(6 downto 0);
|
||||
signal hold_active : std_logic;
|
||||
|
||||
-- Set in first row of double height
|
||||
signal double_high1 : std_logic;
|
||||
-- Set in second row of double height
|
||||
signal double_high2 : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
|
||||
-- Generate flash signal for 3:1 ratio
|
||||
flash <= flash_counter(5) and flash_counter(4);
|
||||
|
||||
-- Sync inputs
|
||||
process(DI_CLOCK,nRESET)
|
||||
begin
|
||||
if nRESET = '0' then
|
||||
di_r <= (others => '0');
|
||||
dew_r <= '0';
|
||||
lose_r <= '0';
|
||||
elsif rising_edge(DI_CLOCK) then
|
||||
if DI_CLKEN = '1' then
|
||||
di_r <= DI;
|
||||
dew_r <= DEW;
|
||||
lose_r <= LOSE;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Register data into pixel clock domain
|
||||
process(CLOCK,nRESET)
|
||||
begin
|
||||
if nRESET = '0' then
|
||||
code <= (others => '0');
|
||||
code_r <= (others => '0');
|
||||
disp_enable_r <= '0';
|
||||
fg_r <= (others => '0');
|
||||
bg_r <= (others => '0');
|
||||
conceal_r <= '0';
|
||||
is_flash_r <= '0';
|
||||
elsif rising_edge(CLOCK) then
|
||||
if CLKEN = '1' then
|
||||
code <= di_r;
|
||||
if pixel_counter = 0 then
|
||||
code_r <= code;
|
||||
disp_enable_r <= disp_enable;
|
||||
fg_r <= fg;
|
||||
bg_r <= bg;
|
||||
conceal_r <= conceal;
|
||||
is_flash_r <= is_flash;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Character row and pixel counters
|
||||
process(CLOCK,nRESET)
|
||||
begin
|
||||
if nRESET = '0' then
|
||||
dew_latch <= '0';
|
||||
lose_latch <= '0';
|
||||
disp_enable <= '0';
|
||||
disp_enable_latch <= '0';
|
||||
double_high1 <= '0';
|
||||
double_high2 <= '0';
|
||||
line_counter <= (others => '0');
|
||||
pixel_counter <= (others => '0');
|
||||
flash_counter <= (others => '0');
|
||||
elsif rising_edge(CLOCK) then
|
||||
if CLKEN = '1' then
|
||||
-- Register syncs for edge detection
|
||||
dew_latch <= dew_r;
|
||||
lose_latch <= lose_r;
|
||||
disp_enable_latch <= disp_enable;
|
||||
|
||||
-- When first entering double-height mode start on top row
|
||||
if double_high = '1' and double_high1 = '0' and double_high2 = '0' then
|
||||
double_high1 <= '1';
|
||||
end if;
|
||||
|
||||
-- Count pixels between 0 and 11
|
||||
if pixel_counter = 11 then
|
||||
-- Start of next character and delayed display enable
|
||||
pixel_counter <= (others => '0');
|
||||
disp_enable <= lose_latch;
|
||||
else
|
||||
pixel_counter <= pixel_counter + 1;
|
||||
end if;
|
||||
|
||||
-- Rising edge of LOSE is the start of the active line
|
||||
if lose_r = '1' and lose_latch = '0' then
|
||||
-- Reset pixel counter - small offset to make the output
|
||||
-- line up with the cursor from the video ULA
|
||||
pixel_counter <= "0010";
|
||||
end if;
|
||||
|
||||
-- Count frames on end of VSYNC (falling edge of DEW)
|
||||
if dew_r = '0' and dew_latch = '1' then
|
||||
flash_counter <= flash_counter + 1;
|
||||
end if;
|
||||
|
||||
if dew_r = '1' then
|
||||
-- Reset line counter and double height state during VSYNC
|
||||
line_counter <= (others => '0');
|
||||
double_high1 <= '0';
|
||||
double_high2 <= '0';
|
||||
else
|
||||
-- Count lines on end of active video (falling edge of disp_enable)
|
||||
if disp_enable = '0' and disp_enable_latch = '1' and (VGA = '0' or CRS = '1') then
|
||||
if line_counter = 9 then
|
||||
line_counter <= (others => '0');
|
||||
|
||||
-- Keep track of which row we are on for double-height
|
||||
-- The double_high flag can be cleared before the end of a row, but if
|
||||
-- double height characters are used anywhere on a row then the double_high1
|
||||
-- flag will be set and remain set until the next row. This is used
|
||||
-- to determine that the bottom half of the characters should be shown if
|
||||
-- double_high is set once again on the row below.
|
||||
double_high1 <= '0';
|
||||
double_high2 <= double_high1;
|
||||
else
|
||||
line_counter <= line_counter + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
|
||||
-- Control character handling
|
||||
process(CLOCK,nRESET)
|
||||
begin
|
||||
if nRESET = '0' then
|
||||
-- Current Attributes
|
||||
fg <= (others => '1');
|
||||
bg <= (others => '0');
|
||||
conceal <= '0';
|
||||
gfx <= '0';
|
||||
gfx_sep <= '0';
|
||||
gfx_hold <= '0';
|
||||
is_flash <= '0';
|
||||
double_high <= '0';
|
||||
-- One-shot versions to support "Set-After" semantics
|
||||
fg_next <= (others => '0');
|
||||
gfx_next <= '0';
|
||||
alpha_next <= '0';
|
||||
gfx_release_next <= '0';
|
||||
is_flash_next <= '0';
|
||||
double_high_next <= '0';
|
||||
unconceal_next <= '0';
|
||||
-- Last graphics character
|
||||
last_gfx <= (others => '0');
|
||||
last_gfx_sep <= '0';
|
||||
elsif rising_edge(CLOCK) then
|
||||
if CLKEN = '1' then
|
||||
-- Reset to start of line defaults
|
||||
if disp_enable = '0' then
|
||||
-- Current Attributes
|
||||
fg <= (others => '1');
|
||||
bg <= (others => '0');
|
||||
conceal <= '0';
|
||||
gfx <= '0';
|
||||
gfx_sep <= '0';
|
||||
gfx_hold <= '0';
|
||||
is_flash <= '0';
|
||||
double_high <= '0';
|
||||
-- One-shot versions to support "Set-After" semantics
|
||||
fg_next <= (others => '0');
|
||||
gfx_next <= '0';
|
||||
alpha_next <= '0';
|
||||
gfx_release_next <= '0';
|
||||
is_flash_next <= '0';
|
||||
double_high_next <= '0';
|
||||
unconceal_next <= '0';
|
||||
-- Last graphics character
|
||||
last_gfx <= (others => '0');
|
||||
last_gfx_sep <= '0';
|
||||
elsif pixel_counter = 0 then
|
||||
-- One-shot versions to support "Set-After" semantics
|
||||
fg_next <= (others => '0');
|
||||
gfx_next <= '0';
|
||||
alpha_next <= '0';
|
||||
gfx_release_next <= '0';
|
||||
is_flash_next <= '0';
|
||||
double_high_next <= '0';
|
||||
unconceal_next <= '0';
|
||||
-- Latch the last graphic character (inc seperation), to support graphics hold
|
||||
if code(5) = '1' then
|
||||
last_gfx <= code;
|
||||
last_gfx_sep <= gfx_sep;
|
||||
end if;
|
||||
-- Latch new control codes at the start of each character
|
||||
if code(6 downto 5) = "00" then
|
||||
if code(3) = '0' then
|
||||
-- 0 would be black but is not allowed so has no effect
|
||||
if code(2 downto 0) /= "000" then
|
||||
-- Colour and graphics setting clears conceal mode - Set After
|
||||
unconceal_next <= '1';
|
||||
-- Select the foreground colout - Set After
|
||||
fg_next <= code(2 downto 0);
|
||||
-- Select graphics or alpha mode - Set After
|
||||
if code(4) = '1' then
|
||||
gfx_next <= '1';
|
||||
else
|
||||
alpha_next <= '1';
|
||||
gfx_release_next <= '1';
|
||||
end if;
|
||||
end if;
|
||||
else
|
||||
case code(4 downto 0) is
|
||||
-- FLASH - Set After
|
||||
when "01000" =>
|
||||
is_flash_next <= '1';
|
||||
-- STEADY - Set At
|
||||
when "01001" =>
|
||||
is_flash <= '0';
|
||||
-- NORMAL HEIGHT - Set At
|
||||
when "01100" =>
|
||||
double_high <= '0';
|
||||
-- Graphics hold character is cleared by a *change* of height
|
||||
if (double_high = '0') then
|
||||
last_gfx <= (others => '0');
|
||||
end if;
|
||||
-- DOUBLE HEIGHT - Set After
|
||||
when "01101" =>
|
||||
double_high_next <= '1';
|
||||
-- Graphics hold character is cleared by a *change* of height
|
||||
if (double_high = '0') then
|
||||
last_gfx <= (others => '0');
|
||||
end if;
|
||||
-- CONCEAL - Set At
|
||||
when "11000" =>
|
||||
conceal <= '1';
|
||||
-- CONTIGUOUS GFX - Set At
|
||||
when "11001" =>
|
||||
gfx_sep <= '0';
|
||||
-- SEPARATED GFX - Set At
|
||||
when "11010" =>
|
||||
gfx_sep <= '1';
|
||||
-- BLACK BACKGROUND - Set At
|
||||
when "11100" =>
|
||||
bg <= (others => '0');
|
||||
-- NEW BACKGROUND - Set At
|
||||
when "11101" =>
|
||||
-- if there is a pending foreground change, then use it
|
||||
if fg_next /= "000" then
|
||||
bg <= fg_next;
|
||||
else
|
||||
bg <= fg;
|
||||
end if;
|
||||
-- HOLD GFX - Set At
|
||||
when "11110" =>
|
||||
gfx_hold <= '1';
|
||||
-- RELEASE GFX - Set After
|
||||
when "11111" =>
|
||||
gfx_release_next <= '1';
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
-- Delay the "Set After" control code effect until the next character
|
||||
if fg_next /= "000" then
|
||||
fg <= fg_next;
|
||||
end if;
|
||||
if gfx_next = '1' then
|
||||
gfx <= '1';
|
||||
end if;
|
||||
if alpha_next = '1' then
|
||||
gfx <= '0';
|
||||
end if;
|
||||
if is_flash_next = '1' then
|
||||
is_flash <= '1';
|
||||
end if;
|
||||
if double_high_next = '1' then
|
||||
double_high <= '1';
|
||||
end if;
|
||||
if gfx_release_next = '1' then
|
||||
gfx_hold <= '0';
|
||||
end if;
|
||||
-- Note, conflicts can arise as setting/clearing happen in different cycles
|
||||
-- e.g. 03 (Alpha Yellow) 18 (Conceal) should leave us in a conceal state
|
||||
if conceal = '1' and unconceal_next = '1' then
|
||||
conceal <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- Character ROM
|
||||
--------------------------------------------------------------------
|
||||
|
||||
-- Generate character rom address in pixel clock domain
|
||||
-- This is done combinatorially since all the inputs are already
|
||||
-- registered and the address is re-registered by the ROM
|
||||
line_addr <= line_counter when double_high = '0' else
|
||||
("0" & line_counter(3 downto 1)) when double_high2 = '0' else
|
||||
("0" & line_counter(3 downto 1)) + 5;
|
||||
|
||||
hold_active <= '1' when gfx_hold = '1' and code_r(6 downto 5) = "00" else '0';
|
||||
|
||||
rom_address1 <= (others => '0') when (double_high = '0' and double_high2 = '1') else
|
||||
gfx & last_gfx & std_logic_vector(line_addr) when hold_active = '1' else
|
||||
gfx & code_r & std_logic_vector(line_addr);
|
||||
|
||||
-- reference row for character rounding
|
||||
rom_address2 <= rom_address1 + 1 when ((double_high = '0' and CRS = '1') or (double_high = '1' and line_counter(0) = '1')) else
|
||||
rom_address1 - 1;
|
||||
|
||||
char_rom : entity work.saa5050_rom_dual_port port map (
|
||||
clock => CLOCK,
|
||||
addressA => rom_address1,
|
||||
QA => rom_data1,
|
||||
addressB => rom_address2,
|
||||
QB => rom_data2
|
||||
);
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- Shift register
|
||||
--------------------------------------------------------------------
|
||||
process(CLOCK,nRESET)
|
||||
variable a : std_logic_vector(11 downto 0);
|
||||
variable b : std_logic_vector(11 downto 0);
|
||||
begin
|
||||
if nRESET = '0' then
|
||||
shift_reg <= (others => '0');
|
||||
elsif rising_edge(CLOCK) then
|
||||
if CLKEN = '1' then
|
||||
if disp_enable_r = '1' and pixel_counter = 0 then
|
||||
-- Character rounding
|
||||
|
||||
-- a is the current row of pixels, doubled up
|
||||
a := rom_data1(5) & rom_data1(5) &
|
||||
rom_data1(4) & rom_data1(4) &
|
||||
rom_data1(3) & rom_data1(3) &
|
||||
rom_data1(2) & rom_data1(2) &
|
||||
rom_data1(1) & rom_data1(1) &
|
||||
rom_data1(0) & rom_data1(0);
|
||||
|
||||
-- b is the adjacent row of pixels, doubled up
|
||||
b := rom_data2(5) & rom_data2(5) &
|
||||
rom_data2(4) & rom_data2(4) &
|
||||
rom_data2(3) & rom_data2(3) &
|
||||
rom_data2(2) & rom_data2(2) &
|
||||
rom_data2(1) & rom_data2(1) &
|
||||
rom_data2(0) & rom_data2(0);
|
||||
|
||||
-- If bit 7 of the ROM data is set then this is a graphics
|
||||
-- character and separated/hold graphics modes apply.
|
||||
-- We don't just assume this to be the case if gfx=1 because
|
||||
-- these modes don't apply to caps even in graphics mode
|
||||
if rom_data1(7) = '1' then
|
||||
-- Apply a mask for separated graphics mode
|
||||
if (hold_active = '0' and gfx_sep = '1') or (hold_active = '1' and last_gfx_sep = '1') then
|
||||
a(10) := '0';
|
||||
a(11) := '0';
|
||||
a(4) := '0';
|
||||
a(5) := '0';
|
||||
if line_counter = 2 or line_counter = 6 or line_counter = 9 then
|
||||
a := (others => '0');
|
||||
end if;
|
||||
end if;
|
||||
else
|
||||
-- Perform character rounding on alpha-numeric characters
|
||||
a := a or
|
||||
(('0' & a(11 downto 1)) and b and not('0' & b(11 downto 1))) or
|
||||
((a(10 downto 0) & '0') and b and not(b(10 downto 0) & '0'));
|
||||
end if;
|
||||
|
||||
-- Load the shift register with the ROM bit pattern
|
||||
-- at the start of each character while disp_enable is asserted.
|
||||
shift_reg <= a;
|
||||
|
||||
else
|
||||
-- Pump the shift register
|
||||
shift_reg <= shift_reg(10 downto 0) & "0";
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
--------------------------------------------------------------------
|
||||
-- Output Pixel Colouring
|
||||
--------------------------------------------------------------------
|
||||
process(CLOCK,nRESET)
|
||||
variable pixel : std_logic;
|
||||
begin
|
||||
|
||||
if nRESET = '0' then
|
||||
R <= '0';
|
||||
G <= '0';
|
||||
B <= '0';
|
||||
elsif rising_edge(CLOCK) then
|
||||
if CLKEN = '1' then
|
||||
pixel := shift_reg(11) and not ((flash and is_flash_r) or conceal_r);
|
||||
|
||||
-- Generate mono output
|
||||
Y <= pixel;
|
||||
|
||||
-- Generate colour output
|
||||
if pixel = '1' then
|
||||
R <= fg_r(0);
|
||||
G <= fg_r(1);
|
||||
B <= fg_r(2);
|
||||
else
|
||||
R <= bg_r(0);
|
||||
G <= bg_r(1);
|
||||
B <= bg_r(2);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end architecture;
|
||||
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// saa5050_rom.v
|
||||
//
|
||||
// Copyright (c) 2015 Stephen J. Leary (sleary@vavi.co.uk)
|
||||
//
|
||||
// This source file is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
module saa5050_rom
|
||||
(
|
||||
input clock,
|
||||
input [MEM_BITS-1:0] address, // Port A address input
|
||||
output [7:0] q
|
||||
);
|
||||
|
||||
parameter MEM_BITS = 12;
|
||||
localparam MEM_SIZE = 2**MEM_BITS;
|
||||
|
||||
reg [MEM_BITS-1:0] address_latched;
|
||||
reg [7:0] mem_data [0:MEM_SIZE-1];
|
||||
|
||||
initial begin
|
||||
$readmemh("saa5050.mif", mem_data);
|
||||
end
|
||||
|
||||
always @(posedge clock) begin
|
||||
|
||||
address_latched <= address;
|
||||
|
||||
end
|
||||
|
||||
assign q = mem_data[address_latched];
|
||||
|
||||
endmodule
|
||||
555
cores/bbc/rtl/saa5050/saa5050_rom_dual_port.vhd
Normal file
555
cores/bbc/rtl/saa5050/saa5050_rom_dual_port.vhd
Normal file
@@ -0,0 +1,555 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
use std.textio.all;
|
||||
|
||||
entity saa5050_rom_dual_port is
|
||||
generic (
|
||||
ADDR_WIDTH : integer := 12;
|
||||
DATA_WIDTH : integer := 8
|
||||
);
|
||||
port(
|
||||
clock : in std_logic;
|
||||
addressA : in std_logic_vector(ADDR_WIDTH-1 downto 0);
|
||||
QA : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
addressB : in std_logic_vector(ADDR_WIDTH-1 downto 0);
|
||||
QB : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end saa5050_rom_dual_port;
|
||||
|
||||
architecture RTL of saa5050_rom_dual_port is
|
||||
|
||||
constant MEM_DEPTH : integer := 2**ADDR_WIDTH;
|
||||
|
||||
type mem_type is array (0 to MEM_DEPTH-1) of signed(DATA_WIDTH-1 downto 0);
|
||||
|
||||
shared variable mem : mem_type := (
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"04",x"04",x"04",x"04",x"00",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0A",x"0A",x"0A",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"06",x"09",x"08",x"1C",x"08",x"08",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"15",x"14",x"0E",x"05",x"15",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"18",x"19",x"02",x"04",x"08",x"13",x"03",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"08",x"14",x"14",x"08",x"15",x"12",x"0D",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"04",x"04",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"02",x"04",x"08",x"08",x"08",x"04",x"02",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"08",x"04",x"02",x"02",x"02",x"04",x"08",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"15",x"0E",x"04",x"0E",x"15",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"04",x"1F",x"04",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"04",x"04",
|
||||
x"08",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"0E",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"01",x"02",x"04",x"08",x"10",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"0A",x"11",x"11",x"11",x"0A",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"0C",x"04",x"04",x"04",x"04",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"01",x"06",x"08",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"01",x"02",x"06",x"01",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"02",x"06",x"0A",x"12",x"1F",x"02",x"02",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"10",x"1E",x"01",x"01",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"06",x"08",x"10",x"1E",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"01",x"02",x"04",x"08",x"08",x"08",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"11",x"0E",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"11",x"0F",x"01",x"02",x"0C",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"04",x"00",x"00",x"00",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"04",x"00",x"00",x"04",x"04",
|
||||
x"08",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"02",x"04",x"08",x"10",x"08",x"04",x"02",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"1F",x"00",x"1F",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"08",x"04",x"02",x"01",x"02",x"04",x"08",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"02",x"04",x"04",x"00",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"17",x"15",x"17",x"10",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"0A",x"11",x"11",x"1F",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"1E",x"11",x"11",x"1E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"10",x"10",x"10",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"11",x"11",x"11",x"1E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"10",x"10",x"1E",x"10",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"10",x"10",x"1E",x"10",x"10",x"10",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"10",x"10",x"13",x"11",x"0F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"1F",x"11",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"04",x"04",x"04",x"04",x"04",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"01",x"01",x"01",x"01",x"01",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"12",x"14",x"18",x"14",x"12",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"10",x"10",x"10",x"10",x"10",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"1B",x"15",x"15",x"11",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"19",x"15",x"13",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"11",x"11",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"1E",x"10",x"10",x"10",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"11",x"11",x"15",x"12",x"0D",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"1E",x"14",x"12",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"10",x"0E",x"01",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"04",x"04",x"04",x"04",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"11",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"0A",x"0A",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"15",x"15",x"15",x"0A",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"0A",x"04",x"0A",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"0A",x"04",x"04",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"01",x"02",x"04",x"08",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"08",x"1F",x"08",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"10",x"10",x"10",x"10",x"16",x"01",x"02",
|
||||
x"04",x"07",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"02",x"1F",x"02",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"0E",x"15",x"04",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0A",x"0A",x"1F",x"0A",x"1F",x"0A",x"0A",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"1F",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0E",x"01",x"0F",x"11",x"0F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"10",x"10",x"1E",x"11",x"11",x"11",x"1E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0F",x"10",x"10",x"10",x"0F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"01",x"01",x"0F",x"11",x"11",x"11",x"0F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0E",x"11",x"1F",x"10",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"02",x"04",x"04",x"0E",x"04",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0F",x"11",x"11",x"11",x"0F",
|
||||
x"01",x"0E",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"10",x"10",x"1E",x"11",x"11",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"00",x"0C",x"04",x"04",x"04",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"00",x"04",x"04",x"04",x"04",x"04",
|
||||
x"04",x"08",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"08",x"08",x"09",x"0A",x"0C",x"0A",x"09",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0C",x"04",x"04",x"04",x"04",x"04",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"1A",x"15",x"15",x"15",x"15",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"1E",x"11",x"11",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0E",x"11",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"1E",x"11",x"11",x"11",x"1E",
|
||||
x"10",x"10",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0F",x"11",x"11",x"11",x"0F",
|
||||
x"01",x"01",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0B",x"0C",x"08",x"08",x"08",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"0F",x"10",x"0E",x"01",x"1E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"04",x"0E",x"04",x"04",x"04",x"02",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"11",x"11",x"11",x"11",x"0F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"11",x"11",x"0A",x"0A",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"11",x"11",x"15",x"15",x"0A",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"11",x"0A",x"04",x"0A",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"11",x"11",x"11",x"11",x"0F",
|
||||
x"01",x"0E",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"1F",x"02",x"04",x"08",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"08",x"08",x"08",x"08",x"09",x"03",x"05",
|
||||
x"07",x"01",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0A",x"0A",x"0A",x"0A",x"0A",x"0A",x"0A",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"18",x"04",x"18",x"04",x"19",x"03",x"05",
|
||||
x"07",x"01",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"00",x"1F",x"00",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"1F",x"1F",x"1F",x"1F",x"1F",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"80",x"80",x"80",x"80",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"80",x"80",x"80",x"80",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"80",x"80",x"80",x"80",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"80",x"80",x"80",x"80",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"B8",x"B8",x"B8",x"B8",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"B8",x"B8",x"B8",x"B8",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"B8",x"B8",x"B8",x"B8",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"87",x"87",x"87",x"87",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"87",x"87",x"87",x"87",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"87",x"87",x"87",x"87",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"87",x"87",x"87",x"87",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"BF",x"BF",x"BF",x"BF",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"BF",x"BF",x"BF",x"BF",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"BF",x"BF",x"BF",x"BF",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"80",
|
||||
x"80",x"80",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"80",x"80",x"80",x"80",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"80",x"80",x"80",x"80",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"80",x"80",x"80",x"80",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"80",x"80",x"80",x"80",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"B8",x"B8",x"B8",x"B8",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"B8",x"B8",x"B8",x"B8",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"B8",x"B8",x"B8",x"B8",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"87",x"87",x"87",x"87",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"87",x"87",x"87",x"87",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"87",x"87",x"87",x"87",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"87",x"87",x"87",x"87",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"BF",x"BF",x"BF",x"BF",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"BF",x"BF",x"BF",x"BF",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"BF",x"BF",x"BF",x"BF",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"B8",
|
||||
x"B8",x"B8",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"17",x"15",x"17",x"10",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"04",x"0A",x"11",x"11",x"1F",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"1E",x"11",x"11",x"1E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"10",x"10",x"10",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"11",x"11",x"11",x"1E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"10",x"10",x"1E",x"10",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"10",x"10",x"1E",x"10",x"10",x"10",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"10",x"10",x"13",x"11",x"0F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"1F",x"11",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"04",x"04",x"04",x"04",x"04",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"01",x"01",x"01",x"01",x"01",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"12",x"14",x"18",x"14",x"12",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"10",x"10",x"10",x"10",x"10",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"1B",x"15",x"15",x"11",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"19",x"15",x"13",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"11",x"11",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"1E",x"10",x"10",x"10",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"11",x"11",x"15",x"12",x"0D",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1E",x"11",x"11",x"1E",x"14",x"12",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0E",x"11",x"10",x"0E",x"01",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"04",x"04",x"04",x"04",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"11",x"11",x"11",x"0E",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"0A",x"0A",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"11",x"15",x"15",x"15",x"0A",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"0A",x"04",x"0A",x"11",x"11",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"11",x"11",x"0A",x"04",x"04",x"04",x"04",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"1F",x"01",x"02",x"04",x"08",x"10",x"1F",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"08",x"1F",x"08",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"10",x"10",x"10",x"10",x"16",x"01",x"02",
|
||||
x"04",x"07",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"02",x"1F",x"02",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"00",x"04",x"0E",x"15",x"04",x"04",x"00",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"00",x"0A",x"0A",x"1F",x"0A",x"1F",x"0A",x"0A",
|
||||
x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"80",x"80",x"80",x"80",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"80",x"80",x"80",x"80",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"80",x"80",x"80",x"80",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"80",x"80",x"80",x"80",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"B8",x"B8",x"B8",x"B8",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"B8",x"B8",x"B8",x"B8",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"B8",x"B8",x"B8",x"B8",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"87",x"87",x"87",x"87",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"87",x"87",x"87",x"87",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"87",x"87",x"87",x"87",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"87",x"87",x"87",x"87",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"BF",x"BF",x"BF",x"BF",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"BF",x"BF",x"BF",x"BF",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"BF",x"BF",x"BF",x"BF",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"87",
|
||||
x"87",x"87",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"80",x"80",x"80",x"80",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"80",x"80",x"80",x"80",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"80",x"80",x"80",x"80",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"80",x"80",x"80",x"80",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"B8",x"B8",x"B8",x"B8",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"B8",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"B8",x"B8",x"B8",x"B8",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"B8",x"B8",x"B8",x"B8",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"87",x"87",x"87",x"87",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"87",x"87",x"87",x"87",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"87",x"87",x"87",x"87",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"87",x"87",x"87",x"87",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"80",x"80",x"80",x"BF",x"BF",x"BF",x"BF",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"B8",x"B8",x"B8",x"BF",x"BF",x"BF",x"BF",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"87",x"87",x"87",x"BF",x"BF",x"BF",x"BF",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00",
|
||||
x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",x"BF",
|
||||
x"BF",x"BF",x"00",x"00",x"00",x"00",x"00",x"00");
|
||||
|
||||
begin
|
||||
|
||||
process(clock) is
|
||||
begin
|
||||
if (rising_edge(clock)) then
|
||||
QA <= std_logic_vector(mem(to_integer(unsigned(addressA))));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clock) is
|
||||
begin
|
||||
if (rising_edge(clock)) then
|
||||
QB <= std_logic_vector(mem(to_integer(unsigned(addressB))));
|
||||
end if;
|
||||
end process;
|
||||
end RTL;
|
||||
@@ -46,8 +46,8 @@ module vidproc (
|
||||
input CLOCK,
|
||||
input CLKEN,
|
||||
input nRESET,
|
||||
input MHZ1_CLKEN, // sync to the clock generator
|
||||
output CLKEN_CRTC,
|
||||
output CLKEN_CRTC_ADR,
|
||||
input ENABLE,
|
||||
input A0,
|
||||
input [7:0] DI_CPU,
|
||||
@@ -77,17 +77,19 @@ reg [3:0] palette [0:15];
|
||||
reg [7:0] shiftreg;
|
||||
|
||||
// Delayed display enable
|
||||
reg delayed_disen;
|
||||
reg delayed_disen1, delayed_disen2;
|
||||
|
||||
// Internal clock enable generation
|
||||
wire clken_pixel;
|
||||
wire clken_fetch;
|
||||
wire mhz4_clken;
|
||||
reg [3:0] clken_counter;
|
||||
|
||||
// Cursor generation - can span up to 32 pixels
|
||||
// Segments 0 and 1 are 8 pixels wide
|
||||
// Segment 2 is 16 pixels wide
|
||||
wire cursor_invert;
|
||||
reg cursor_invert_delayed;
|
||||
reg cursor_active;
|
||||
reg [1:0] cursor_counter;
|
||||
|
||||
@@ -96,7 +98,7 @@ integer V2V_colour;
|
||||
|
||||
always @(posedge CLOCK) begin : process_1
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
if (~nRESET) begin
|
||||
r0_cursor0 <= 1'b 0;
|
||||
r0_cursor1 <= 1'b 0;
|
||||
r0_cursor2 <= 1'b 0;
|
||||
@@ -110,7 +112,7 @@ always @(posedge CLOCK) begin : process_1
|
||||
end
|
||||
end
|
||||
else begin
|
||||
if (ENABLE === 1'b 1) begin
|
||||
if (ENABLE) begin
|
||||
if (A0 === 1'b 0) begin
|
||||
|
||||
// Access control register
|
||||
@@ -135,90 +137,87 @@ end
|
||||
// Pixel clock can be divided by 1,2,4 or 8 depending on the value
|
||||
// programmed at r0_pixel_rate
|
||||
// 00 = /8, 01 = /4, 10 = /2, 11 = /1
|
||||
|
||||
assign clken_pixel = r0_pixel_rate === 2'b 11 ? CLKEN :
|
||||
r0_pixel_rate === 2'b 10 ? CLKEN & ~clken_counter[0] :
|
||||
r0_pixel_rate === 2'b 01 ? CLKEN & ~(clken_counter[0] | clken_counter[1]) :
|
||||
CLKEN & ~(clken_counter[0] | clken_counter[1] | clken_counter[2]);
|
||||
r0_pixel_rate === 2'b 10 ? CLKEN & clken_counter[0] :
|
||||
r0_pixel_rate === 2'b 01 ? CLKEN & clken_counter[0] & clken_counter[1] :
|
||||
CLKEN & clken_counter[0] & clken_counter[1] & ~clken_counter[2];
|
||||
|
||||
// The CRT controller is always enabled in the 15th cycle, so that the result
|
||||
// is ready for latching into the shift register in cycle 0. If 2 MHz mode is
|
||||
// is ready for latching into the shift register in cycle 3. If 2 MHz mode is
|
||||
// selected then the CRTC is also enabled in the 7th cycle
|
||||
assign CLKEN_CRTC = CLKEN & clken_counter[0] & clken_counter[1] & clken_counter[2] &
|
||||
(clken_counter[3] | r0_crtc_2mhz);
|
||||
|
||||
// extra signal for crtc address setup a little earlier
|
||||
assign CLKEN_CRTC_ADR = CLKEN & clken_counter[0] & clken_counter[1] & !clken_counter[2] &
|
||||
(clken_counter[3] | r0_crtc_2mhz);
|
||||
|
||||
// The result is fetched from the CRTC in cycle 0 and also cycle 8 if 2 MHz
|
||||
// The result is fetched from the RAM in cycle 11 and also cycle 3 if 2 MHz
|
||||
// mode is selected. This is used for reloading the shift register as well as
|
||||
// counting cursor pixels
|
||||
assign clken_fetch = CLKEN & ~(clken_counter[0] | clken_counter[1] | clken_counter[2] | clken_counter[3] & ~r0_crtc_2mhz);
|
||||
|
||||
assign mhz4_clken = CLKEN & ~clken_counter[2] & clken_counter[1] & clken_counter[0];
|
||||
assign clken_fetch = mhz4_clken & (clken_counter[3] | r0_crtc_2mhz);
|
||||
|
||||
wire [7:0] shiftreg_nxt = clken_fetch ? DI_RAM :
|
||||
clken_pixel ? {shiftreg[6:0], 1'b 1} : shiftreg;
|
||||
|
||||
always @(posedge CLOCK) begin : process_2
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
clken_counter <= 'd0;
|
||||
if (~nRESET) begin
|
||||
clken_counter <= 0;
|
||||
end
|
||||
else if (CLKEN === 1'b 1 ) begin
|
||||
|
||||
// Increment internal cycle counter during each video clock
|
||||
clken_counter <= clken_counter + 1;
|
||||
else if (CLKEN) begin
|
||||
if (MHZ1_CLKEN)
|
||||
clken_counter <= 0;
|
||||
else
|
||||
// Increment internal cycle counter during each video clock
|
||||
clken_counter <= clken_counter + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
// Fetch control
|
||||
|
||||
always @(posedge CLOCK) begin : process_3
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
|
||||
shiftreg <= 'd0;
|
||||
|
||||
if (~nRESET) begin
|
||||
shiftreg <= 0;
|
||||
end
|
||||
else begin
|
||||
|
||||
shiftreg <= shiftreg_nxt;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// Cursor generation
|
||||
assign cursor_invert = cursor_active & (r0_cursor0 & ~(cursor_counter[0] | cursor_counter[1]) |
|
||||
r0_cursor1 & cursor_counter[0] & ~cursor_counter[1] | r0_cursor2 &
|
||||
cursor_counter[1]);
|
||||
(r0_cursor1 & cursor_counter[0] & ~cursor_counter[1]) |
|
||||
(r0_cursor2 & cursor_counter[1]));
|
||||
|
||||
// delayed cursor for teletext
|
||||
always @(posedge CLOCK) if (mhz4_clken) cursor_invert_delayed <= cursor_invert;
|
||||
|
||||
always @(posedge CLOCK) begin : process_4
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
cursor_active <= 'd0;
|
||||
cursor_counter <= 'd0;
|
||||
if (~nRESET) begin
|
||||
cursor_active <= 0;
|
||||
cursor_counter <= 0;
|
||||
end
|
||||
else if (clken_fetch === 1'b 1 ) begin
|
||||
if ((CURSOR | cursor_active) === 1'b 1) begin
|
||||
else if (clken_fetch) begin
|
||||
|
||||
if (CURSOR | cursor_active) begin
|
||||
// Latch cursor
|
||||
cursor_active <= 1'b 1;
|
||||
cursor_active <= 1;
|
||||
|
||||
// Reset on counter wrap
|
||||
if (cursor_counter === 2'b 11) begin
|
||||
cursor_active <= 1'b 0;
|
||||
cursor_active <= 0;
|
||||
end
|
||||
|
||||
// Increment counter
|
||||
if (cursor_active === 1'b 0) begin
|
||||
if (!cursor_active) begin
|
||||
|
||||
// Reset
|
||||
cursor_counter <= {2{1'b 0}};
|
||||
cursor_counter <= 0;
|
||||
|
||||
// Increment
|
||||
end
|
||||
else begin
|
||||
cursor_counter <= cursor_counter + 1;
|
||||
// Increment
|
||||
cursor_counter <= cursor_counter + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -226,7 +225,7 @@ end
|
||||
|
||||
// Pixel generation
|
||||
// The new shift register contents are loaded during
|
||||
// cycle 0 (and 8) but will not be read here until the next cycle.
|
||||
// cycle 11 (and 3) but will not be read here until the next cycle.
|
||||
// By running this process on every single video tick instead of at
|
||||
// the pixel rate we ensure that the resulting delay is minimal and
|
||||
// constant (running this at the pixel rate would cause
|
||||
@@ -239,30 +238,35 @@ end
|
||||
// bit 1 - Not GREEN
|
||||
// bit 0 - Not RED
|
||||
|
||||
wire [3:0] palette_a = {shiftreg[7], shiftreg[5], shiftreg[3], shiftreg[1]};
|
||||
wire [3:0] dot_val = palette[palette_a];
|
||||
wire [3:0] palette_a = {shiftreg[7], shiftreg[5], shiftreg[3], shiftreg[1]};
|
||||
wire [3:0] dot_val = palette[palette_a];
|
||||
|
||||
// Apply flash inversion if required
|
||||
wire red_val = dot_val[3] & r0_flash ^ ~dot_val[0];
|
||||
wire green_val = dot_val[3] & r0_flash ^ ~dot_val[1];
|
||||
wire blue_val = dot_val[3] & r0_flash ^ ~dot_val[2];
|
||||
wire red_val = dot_val[3] & r0_flash ^ ~dot_val[0];
|
||||
wire green_val = dot_val[3] & r0_flash ^ ~dot_val[1];
|
||||
wire blue_val = dot_val[3] & r0_flash ^ ~dot_val[2];
|
||||
|
||||
// Display enable signal delayed by one clock
|
||||
always @(posedge CLOCK) begin
|
||||
if (mhz4_clken) begin
|
||||
delayed_disen1 <= DISEN;
|
||||
delayed_disen2 <= delayed_disen1;
|
||||
end
|
||||
end
|
||||
wire delayed_disen = r0_crtc_2mhz ? delayed_disen1 : delayed_disen2;
|
||||
|
||||
always @(posedge CLOCK) begin
|
||||
|
||||
if (nRESET === 1'b 0) begin
|
||||
|
||||
R <= 'd0;
|
||||
G <= 'd0;
|
||||
B <= 'd0;
|
||||
|
||||
delayed_disen <= 'd0;
|
||||
|
||||
if (~nRESET) begin
|
||||
R <= 0;
|
||||
G <= 0;
|
||||
B <= 0;
|
||||
end
|
||||
else if (CLKEN === 1'b1) begin
|
||||
else if (CLKEN) begin
|
||||
|
||||
// To output
|
||||
// FIXME: INVERT option
|
||||
if (r0_teletext === 1'b0) begin
|
||||
if (!r0_teletext) begin
|
||||
|
||||
// Cursor can extend outside the bounds of the screen, so
|
||||
// it is not affected by DISEN
|
||||
@@ -273,17 +277,14 @@ always @(posedge CLOCK) begin
|
||||
end
|
||||
else begin
|
||||
|
||||
R <= R_IN ^ cursor_invert;
|
||||
G <= G_IN ^ cursor_invert;
|
||||
B <= B_IN ^ cursor_invert;
|
||||
R <= R_IN ^ cursor_invert_delayed;
|
||||
G <= G_IN ^ cursor_invert_delayed;
|
||||
B <= B_IN ^ cursor_invert_delayed;
|
||||
|
||||
end
|
||||
|
||||
// Display enable signal delayed by one clock
|
||||
delayed_disen <= DISEN;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
endmodule // module vidproc
|
||||
|
||||
|
||||
Reference in New Issue
Block a user