Line 52... |
Line 52... |
// Video output
|
// Video output
|
output r, //
|
output r, //
|
output g, // RGB TTL signal
|
output g, // RGB TTL signal
|
output b, // with separate bright
|
output b, // with separate bright
|
output i, // and composite sync
|
output i, // and composite sync
|
|
output [7:0] rgbulaplus, // 8-bit RGB value for current pixel, ULA+
|
|
output ulaplus_enabled, // =1 if ULAPlus enabled. To help selecting the right outputs to the RGB DAC
|
output csync //
|
output csync //
|
);
|
);
|
|
|
reg [2:0] BorderColor = 3'b100;
|
reg [2:0] BorderColor = 3'b100;
|
reg TimexHiColorMode = 0;
|
reg TimexHiColorMode = 0;
|
|
|
reg ULAPlusConfig = 0;
|
reg ULAPlusConfig = 0; // bit 0 of reg.64
|
reg [7:0] ULAPlusAddrReg = 0;
|
reg [7:0] ULAPlusAddrReg = 0; // ULA+ register address, BF3Bh port.
|
|
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 addrportsel = !iorq_n && a[0] && !a[2] && (a[7:6]==2'b00) && (a[15:14]==2'b10); // port BF3Bh
|
wire dataportsel = !iorq_n && a[0] && !a[2] && (a[7:6]==2'b00) && (a[15:14]==2'b11); // port FF3Bh
|
wire dataportsel = !iorq_n && a[0] && !a[2] && (a[7:6]==2'b00) && (a[15:14]==2'b11); // port FF3Bh
|
wire cpu_writes_palette = dataportsel && !wr_n && (ULAPlusAddrReg[7:6]==2'b00);
|
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;
|
reg [5:0] paletteaddr; // address bus of palette RAM
|
wire [7:0] palettedout;
|
wire [7:0] palettedout; // data out port of palette RAM
|
reg palettewe;
|
reg palettewe; // WE signal of palette RAM (palette RAM is always selected and output enabled)
|
|
|
ram64bytes palette (
|
ram64bytes palette (
|
.clk(clk14),
|
.clk(clk14), // only for write operations. Read operations are asynchronous
|
.a(paletteaddr),
|
.a(paletteaddr),
|
.din(din),
|
.din(din),
|
.dout(palettedout),
|
.dout(palettedout),
|
.we(palettewe)
|
.we(palettewe) // RAM is written if WE is enabled at the rising edge of clk
|
);
|
);
|
|
|
// Pixel clock
|
// Pixel clock
|
reg clk7 = 0;
|
reg clk7 = 0;
|
always @(posedge clk14)
|
always @(posedge clk14)
|
Line 299... |
Line 302... |
rVOE = !rd_n;
|
rVOE = !rd_n;
|
rVWE = !wr_n;
|
rVWE = !wr_n;
|
end
|
end
|
end
|
end
|
|
|
// Palette addr 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] };
|
end
|
end
|
Line 313... |
Line 316... |
end
|
end
|
else if (dataportsel) begin // if CPU requests access, give it palette control
|
else if (dataportsel) begin // if CPU requests access, give it palette control
|
paletteaddr = ULAPlusAddrReg[5:0];
|
paletteaddr = ULAPlusAddrReg[5:0];
|
palettewe = cpu_writes_palette;
|
palettewe = cpu_writes_palette;
|
end
|
end
|
else begin
|
else begin // if palette RAM is not being used to display pixels, and the CPU doesn't need it, put the border color address
|
palettewe = 0; // blocking assignment, so we will first deassert WE at palette RAM...
|
palettewe = 0; // blocking assignment, so we will first deassert WE at palette RAM...
|
paletteaddr = {3'b001, BorderColor}; // ... then, we can change the palette RAM address
|
paletteaddr = {3'b001, BorderColor}; // ... then, we can change the palette RAM address
|
end
|
end
|
end
|
end
|
|
|
|
//ULA+ : palette reading and attribute generation
|
|
// First buffers for paper and ink
|
|
reg [7:0] ULAPlusPaper = 0;
|
|
reg [7:0] ULAPlusInk = 0;
|
|
reg [7:0] ULAPlusBorder = 0;
|
|
wire ULAPlusPixel = SRegister[7];
|
|
always @(negedge clk14) begin
|
|
if (Border_n && (hc[3:0]==10 || hc[3:0]==14) && !clk7) // this happens 1/2 clk7 after address is settled
|
|
ULAPlusPaper <= palettedout;
|
|
else if (Border_n && (hc[3:0]==11 || hc[3:0]==15) && !clk7) // this happens 1/2 clk7 after address is settled
|
|
ULAPlusInk <= palettedout;
|
|
else if (hc[3:0]==12 && !dataportsel) // On cycle 12, palette RAM is not used to retrieve ink/paper color. If CPU is not reclaiming it...
|
|
ULAPlusBorder <= palettedout; //... take the chance to update the BorderColor register by reading the palette RAM. The address
|
|
end // presented at the palette RAM address bus will be 001BBB, where BBB is the border color code.
|
|
// Second buffers for paper and ink
|
|
reg [7:0] ULAPlusPaperOut = 0;
|
|
reg [7:0] ULAPlusInkOut = 0;
|
|
always @(negedge AOLatch_n) begin
|
|
if (!VidEN_n) begin // if it's "paper time", load output buffers with current ink and paper color
|
|
ULAPlusPaperOut <= ULAPlusPaper;
|
|
ULAPlusInkOut <= ULAPlusInk;
|
|
end
|
|
else begin // if not, it's "border/blanking time", so load output buffers with current border color
|
|
ULAPlusPaperOut <= ULAPlusBorder;
|
|
ULAPlusInkOut <= ULAPlusBorder;
|
|
end
|
|
end
|
|
// ULA+ : final RGB generation depending on pixel value and blanking period.
|
|
reg [7:0] rRGBULAPlus;
|
|
assign rgbulaplus = rRGBULAPlus;
|
|
always @(*) begin
|
|
if (HBlank_n && VBlank_n)
|
|
rRGBULAPlus = (ULAPlusPixel)? ULAPlusInkOut : ULAPlusPaperOut;
|
|
else
|
|
rRGBULAPlus = 8'h00;
|
|
end
|
|
|
// CPU contention
|
// CPU contention
|
reg CPUClk = 0;
|
reg CPUClk = 0;
|
assign clkcpu = CPUClk;
|
assign clkcpu = CPUClk;
|
reg ioreqtw3 = 0;
|
reg ioreqtw3 = 0;
|
reg mreqt23 = 0;
|
reg mreqt23 = 0;
|
Line 347... |
Line 387... |
always @(posedge CPUClk) begin
|
always @(posedge CPUClk) begin
|
ioreqtw3 <= ioreq_n;
|
ioreqtw3 <= ioreq_n;
|
mreqt23 <= mreq_n;
|
mreqt23 <= mreq_n;
|
end
|
end
|
|
|
// ULA+ palette management
|
// ULA+ : palette management
|
always @(posedge clk7 or posedge reset) begin
|
always @(posedge clk7 or posedge reset) begin
|
if (reset)
|
if (reset)
|
ULAPlusConfig <= 0;
|
ULAPlusConfig <= 0;
|
else begin
|
else begin
|
if (addrportsel && !wr_n)
|
if (addrportsel && !wr_n)
|