Line 21... |
Line 21... |
|
|
`define cyclestart(a,b) ((a)==(b))
|
`define cyclestart(a,b) ((a)==(b))
|
`define cycleend(a,b) ((a)==(b+1))
|
`define cycleend(a,b) ((a)==(b+1))
|
|
|
module ula(
|
module ula(
|
input clk14, // 14MHz master clock
|
input clk28, // 28MHz master clock
|
input reset_n, // to reset the ULA to normal color mode.
|
input reset_n, // to reset the ULA to normal color mode.
|
// CPU interfacing
|
// CPU interfacing
|
input [15:0] a, // Address bus from CPU (not all lines are used)
|
input a15, // Address bus from CPU (not all lines are used)
|
input [7:0] din, // Input data bus from CPU
|
input a14,
|
output [7:0] dout, // Output data bus to CPU
|
input a7,
|
|
input a6,
|
|
input a2,
|
|
inout [7:0] d, // Data bus from/to CPU
|
input mreq_n, // MREQ from CPU
|
input mreq_n, // MREQ from CPU
|
input ioreq_n, // IORQ+A0 from main board
|
input ioreq_n, // IORQ+A0 from main board
|
input iorq_n, // IORQ from CPU
|
input iorq_n, // IORQ from CPU
|
input rd_n, // RD from CPU
|
input rd_n, // RD from CPU
|
input wr_n, // WR from CPU
|
input wr_n, // WR from CPU
|
output clkcpu, // CLK to CPU
|
output clkcpu, // CLK to CPU
|
output msk_int_n, // Vertical retrace interrupt, to CPU
|
output msk_int_n, // Vertical retrace interrupt, to CPU
|
// VRAM interfacing
|
// VRAM interfacing
|
output [13:0] va, // Address bus to VRAM (16K)
|
output [6:0] va, // Address bus to VRAM (16K)
|
input [7:0] vramdout,// Data from VRAM to ULA/CPU
|
output ras_n, //
|
output [7:0] vramdin,// Data from CPU to VRAM
|
output cas_n, // Control signals for VRAM
|
output vramoe, //
|
output dramwe_n, //
|
output vramcs, // Control signals for VRAM
|
|
output vramwe, //
|
|
// ULA I/O
|
// ULA I/O
|
input ear, //
|
input ear, //
|
output mic, // I/O ports
|
output mic, // I/O ports
|
output spk, //
|
output spk, //
|
input [4:0] kbcolumns, // Keyboard columns
|
input [4:0] kbcolumns, // Keyboard columns
|
Line 62... |
Line 63... |
reg TimexHiColorMode = 0;
|
reg TimexHiColorMode = 0;
|
|
|
reg ULAPlusConfig = 0; // bit 0 of reg.64
|
reg ULAPlusConfig = 0; // bit 0 of reg.64
|
reg [7:0] ULAPlusAddrReg = 0; // ULA+ register address, BF3Bh port.
|
reg [7:0] ULAPlusAddrReg = 0; // ULA+ register address, BF3Bh port.
|
assign ulaplus_enabled = ULAPlusConfig;
|
assign ulaplus_enabled = ULAPlusConfig;
|
wire addrportsel = !iorq_n && a[0] && !a[2] && (a[7:6]==2'b00) && (a[15:14]==2'b10); // port BF3Bh
|
wire a0 = (!ioreq_n && !iorq_n)? 0 : 1; // Regenerate a valid (for IORQ access) a0 signal
|
wire dataportsel = !iorq_n && a[0] && !a[2] && (a[7:6]==2'b00) && (a[15:14]==2'b11); // port FF3Bh
|
wire addrportsel = !iorq_n && a0 && !a2 && !a7 && !a6 && a15 && !a14; // port BF3Bh
|
|
wire dataportsel = !iorq_n && a0 && !a2 && !a7 && !a6 && a15 && a14; // port FF3Bh
|
wire cpu_writes_palette = dataportsel && !wr_n && (ULAPlusAddrReg[7:6]==2'b00); //=1 if CPU wants to write a palette entry to RAM
|
wire cpu_writes_palette = dataportsel && !wr_n && (ULAPlusAddrReg[7:6]==2'b00); //=1 if CPU wants to write a palette entry to RAM
|
reg [5:0] paletteaddr; // address bus of palette RAM
|
reg [5:0] paletteaddr; // address bus of palette RAM
|
wire [7:0] palettedout; // data out port of palette RAM
|
wire [7:0] palettedout; // data out port of palette RAM
|
reg palettewe; // WE signal of palette RAM (palette RAM is always selected and output enabled)
|
reg palettewe; // WE signal of palette RAM (palette RAM is always selected and output enabled)
|
|
|
|
// Clocks
|
|
reg [1:0] clk28div = 0;
|
|
always @(posedge clk28) // 28MHz for RAS/CAS generation
|
|
clk28div <= clk28div + 1;
|
|
wire clk7 = clk28div[1]; // For pixel operations
|
|
wire clk14 = clk28div[0]; // For palette operations
|
|
|
|
// Palette RAM instantiation
|
ram64bytes palette (
|
ram64bytes palette (
|
.clk(clk14), // only for write operations. Read operations are asynchronous
|
.clk(clk14), // only for write operations. Read operations are asynchronous
|
.a(paletteaddr),
|
.a(paletteaddr),
|
.din(din),
|
.din(din),
|
.dout(palettedout),
|
.dout(palettedout),
|
.we(palettewe) // RAM is written if WE is enabled at the rising edge of clk
|
.we(palettewe) // RAM is written if WE is enabled at the rising edge of clk
|
);
|
);
|
|
|
// Pixel clock
|
|
reg clk7 = 0;
|
|
always @(posedge clk14)
|
|
clk7 <= !clk7;
|
|
|
|
// Horizontal counter
|
// Horizontal counter
|
reg [8:0] hc = 0;
|
reg [8:0] hc = 0;
|
always @(posedge clk7) begin
|
always @(posedge clk7) begin
|
if (hc==447)
|
if (hc==447)
|
hc <= 0;
|
hc <= 0;
|
Line 253... |
Line 258... |
end
|
end
|
|
|
//CSync generation
|
//CSync generation
|
assign csync = HSync_n & VSync_n;
|
assign csync = HSync_n & VSync_n;
|
|
|
// VRAM address and control line generation
|
// VRAM address and control line generation (TO-DO)
|
reg [13:0] rVA = 0;
|
reg [13:0] rVA = 0;
|
reg rVCS = 0;
|
reg rVCS = 0;
|
reg rVOE = 0;
|
reg rVOE = 0;
|
reg rVWE = 0;
|
reg rVWE = 0;
|
assign va = rVA;
|
|
assign vramcs = rVCS;
|
|
assign vramoe = rVOE;
|
|
assign vramwe = rVWE;
|
|
// Latches to hold delayed versions of V and H counters
|
// Latches to hold delayed versions of V and H counters
|
reg [8:0] v = 0;
|
reg [8:0] v = 0;
|
reg [8:0] c = 0;
|
reg [8:0] c = 0;
|
// Address and control line multiplexor ULA/CPU
|
// Address and control line multiplexor ULA/CPU
|
always @(negedge clk7) begin
|
always @(negedge clk7) begin
|
if (Border_n && (hc[3:0]==4'b0111 || hc[3:0]==4'b1011)) begin // cycles 7 and 11: load V and C from VC and HC
|
if (Border_n && (hc[3:0]==7 || hc[3:0]==11)) begin // cycles 7 and 11: load V and C from VC and HC
|
c <= hc;
|
c <= hc;
|
v <= vc;
|
v <= vc;
|
end
|
end
|
end
|
end
|
// Address and control line multiplexor ULA/CPU
|
// Address and control line multiplexor ULA/CPU
|
always @(*) begin
|
always @(*) begin
|
if (Border_n && (hc[3:0]==4'b1000 || hc[3:0]==4'b1001 || hc[3:0]==4'b1100 || hc[3:0]==4'b1101)) begin // cycles 8 and 12: present attribute address to VRAM
|
if (Border_n && (hc[3:0]==8 || hc[3:0]==9 || hc[3:0]==12 || hc[3:0]==13)) begin // cycles 8 and 12: present attribute address to VRAM
|
rVA = (TimexHiColorMode)? {1'b1,v[7:6],v[2:0],v[5:3],c[7:3]} : // (cycles 9 and 13 load attr byte).
|
rVA = (TimexHiColorMode)? {1'b1,v[7:6],v[2:0],v[5:3],c[7:3]} : // (cycles 9 and 13 load attr byte).
|
{4'b0110,v[7:3],c[7:3]}; // Attribute address depends upon the mode selected
|
{4'b0110,v[7:3],c[7:3]}; // Attribute address depends upon the mode selected
|
rVCS = 1;
|
rVCS = 1;
|
rVOE = !hc[0];
|
rVOE = !hc[0];
|
rVWE = 0;
|
rVWE = 0;
|
end
|
end
|
else if (Border_n && (hc[3:0]==4'b1010 || hc[3:0]==4'b1011 || hc[3:0]==4'b1110 || hc[3:0]==4'b1111)) begin // cycles 10 and 14: present display address to VRAM
|
else if (Border_n && (hc[3:0]==10 || hc[3:0]==11 || hc[3:0]==14 || hc[3:0]==15)) begin // cycles 10 and 14: present display address to VRAM
|
rVA = {1'b0,v[7:6],v[2:0],v[5:3],c[7:3]}; // (cycles 11 and 15 load display byte)
|
rVA = {1'b0,v[7:6],v[2:0],v[5:3],c[7:3]}; // (cycles 11 and 15 load display byte)
|
rVCS = 1;
|
rVCS = 1;
|
rVOE = !hc[0];
|
rVOE = !hc[0];
|
rVWE = 0;
|
rVWE = 0;
|
end
|
end
|
else if (Border_n && hc[3:0]==4'b0000) begin
|
else if (Border_n && hc[3:0]==0) begin
|
rVA = a[13:0];
|
rVA = a[13:0];
|
rVCS = 0;
|
rVCS = 0;
|
rVOE = 0;
|
rVOE = 0;
|
rVWE = 0;
|
rVWE = 0;
|
end
|
end
|
else begin // when VRAM is not in use by ULA, give it to CPU
|
else begin // when VRAM is not in use by ULA, give it to CPU
|
rVA = a[13:0];
|
|
rVCS = !a[15] & a[14] & !mreq_n;
|
|
rVOE = !rd_n;
|
|
rVWE = !wr_n;
|
|
end
|
end
|
end
|
end
|
|
|
|
// RAS/CAS/DRAMWE generation
|
|
reg rRAS_n = 1;
|
|
reg rCAS_n = 1;
|
|
reg rDRAMWE_n = 1;
|
|
wire [5:0] RCycle = {hc[3:0],clk28div};
|
|
always @(posedge clk28) begin
|
|
|
|
|
|
|
|
|
// ULA+ : palette RAM address and control bus multiplexing
|
// ULA+ : palette RAM address and control bus multiplexing
|
always @(*) begin
|
always @(*) begin
|
if (Border_n && (hc[3:0]==10 || hc[3:0]==14)) begin // present address of paper to palette RAM
|
if (Border_n && (hc[3:0]==10 || hc[3:0]==14)) begin // present address of paper to palette RAM
|
palettewe = 0;
|
palettewe = 0;
|
paletteaddr = { AttrReg[7:6],1'b1,AttrReg[5:3] };
|
paletteaddr = { AttrReg[7:6],1'b1,AttrReg[5:3] };
|