187 lines
6.2 KiB
Systemverilog
187 lines
6.2 KiB
Systemverilog
/******************************************************************************
|
|
* SE-VGA
|
|
* Top-level module
|
|
* techav
|
|
* 2021-08-04
|
|
******************************************************************************
|
|
* Pulls together all the smaller modules to form the SE-VGA adapter
|
|
*****************************************************************************/
|
|
|
|
module sevga (
|
|
input wire nReset, // System reset signal
|
|
input wire pixClk, // 25.175MHz pixel clock
|
|
output wire nhSync, // HSync signal
|
|
output wire nvSync, // VSync signal
|
|
output wire vidOut, // 1-bit Monochrome video signal
|
|
|
|
output logic [14:0] vramAddr, // VRAM Address bus
|
|
inout logic [7:0] vramData, // VRAM Data bus
|
|
output wire nvramOE, // VRAM Read strobe
|
|
output wire nvramWE, // VRAM Write strobe
|
|
output wire nvramCE0, // VRAM Main chip select signal
|
|
output wire nvramCE1, // VRAM Alt chip select signal
|
|
|
|
input logic [23:1] cpuAddr, // CPU Address bus
|
|
input logic [15:0] cpuData, // CPU Data bus
|
|
input wire ncpuAS, // CPU Address Strobe signal
|
|
input wire ncpuUDS, // CPU Upper Data Strobe signal
|
|
input wire ncpuLDS, // CPU Lower Data Strobe signal
|
|
input wire cpuRnW, // CPU Read/Write select signal
|
|
input logic [2:0] ramSize // Select installed RAM size
|
|
);
|
|
|
|
/******************************************************************************
|
|
* Initial Video Signal Timing
|
|
* The following four functions establish the basic XGA signal timing and
|
|
* assert the horizontal and vertical sync signals as appropriate.
|
|
* These functions are the minimum required for a signal presence detect test.
|
|
*****************************************************************************/
|
|
logic [10:0] hCount; // 0..1343
|
|
logic [9:0] vCount; // 0..805
|
|
|
|
// horizontal counter
|
|
always @(negedge pixClk or negedge nReset) begin
|
|
if(!nReset) hCount <= 0;
|
|
else begin
|
|
if(hCount < 1343) hCount <= hCount + 1;
|
|
else hCount <= 0;
|
|
end
|
|
end
|
|
|
|
// vertical counter
|
|
always @(negedge pixClk or negedge nReset) begin
|
|
if(!nReset) vCount <= 0;
|
|
else begin
|
|
if(vCount < 805) vCount <= vCount + 1;
|
|
else vCount <= 0;
|
|
end
|
|
end
|
|
|
|
// horizontal and vertical sync signals
|
|
always_comb begin
|
|
if(hCount >= 1049 && hCount < 1184) nhSync <= 0;
|
|
else nhSync <= 1;
|
|
|
|
if(vCount >= 729 && vCount < 735) nvSync <= 0;
|
|
else nvSync <= 1;
|
|
end
|
|
|
|
/******************************************************************************
|
|
* Useful signals
|
|
* Here we break out a few useful signals, derived from the timing above, that
|
|
* will help us elsewhere.
|
|
*****************************************************************************/
|
|
wire hActive, vActive; // active video signals. vidout black when negated
|
|
wire vidActive; // active when both hActive and vActive asserted
|
|
wire hLoad; // load pixel data from vram when asserted
|
|
|
|
assign vidActive = hActive & vidActive;
|
|
|
|
always_comb begin
|
|
if(hCount >= 1 && hCount < 1025) hActive <= 1;
|
|
else hActive <= 0;
|
|
|
|
if(vCount >= 0 && vCount < 684) vActive <= 1;
|
|
else vActive <= 0;
|
|
|
|
if(hCount >= 0 && hCount < 1024 && vActive) hLoad <= 1;
|
|
else hLoad <= 0;
|
|
end
|
|
|
|
/******************************************************************************
|
|
* Video Output Sequencing
|
|
* Here is the primary video output shift register sequencing.
|
|
* With these functions in place, it should be possible to strap the VRAM data
|
|
* signals and see the strapped pattern output on screen.
|
|
*****************************************************************************/
|
|
logic [8:0] vidData; // the video data we are displaying
|
|
wire [2:0] vidSeq; // sequence counter, derived from hCount
|
|
wire tick, tock; // even/odd pulses of pixel clock divided by 2
|
|
|
|
assign vidSeq = hCount[3:1];
|
|
assign tick = !hCount[0];
|
|
assign tock = hCount[0];
|
|
|
|
always @(negedge pixClk or negedge nReset) begin
|
|
if(!nReset) vidData <= 0;
|
|
else
|
|
if(tock && hLoad && vidSeq == 0) begin
|
|
// store the VRAM data in vidData[8:1]
|
|
//vidData[0] <= vidData[1]; // this should actually have already been done
|
|
vidData[8:1] <= vramData;
|
|
end else if(tick && hLoad) begin
|
|
// shift vidData
|
|
vidData[7:0] <= vidData[8:1];
|
|
vidData[8] <= 0;
|
|
end
|
|
end
|
|
end
|
|
|
|
always_comb begin
|
|
// here is where the shifted video data actually gets output
|
|
if(vidActive) vidOut <= ~vidData[0];
|
|
else vidOut <= 0;
|
|
|
|
// vram read signal can be asserted here
|
|
if(vidActive && vidSeq == 0) nvramOE <= 0;
|
|
else nvramOE <= 1;
|
|
end
|
|
|
|
|
|
/******************************************************************************
|
|
* CPU Bus Snooping
|
|
* Watch the CPU bus for writes to the video buffer regions of memory, cache
|
|
* the data internally until a write slot is available, then store in VRAM.
|
|
* This is the last step, and it's a big one. Once this is in place and
|
|
* operational, the adapter should be fully operational.
|
|
*****************************************************************************/
|
|
|
|
// to remember for later:
|
|
// vramCE[x] should be asserted when vidSeq == 0
|
|
// vramOE should be asserted when vidSeq == 0 && vidActive
|
|
// vramWE should be asserted on tock pulses of write sequences
|
|
|
|
/*
|
|
// link module that snoops cpu writes
|
|
cpusnoop cpusnp(
|
|
.nReset(nReset),
|
|
.pixClock(pixClk),
|
|
.seq(hCount[2:0]),
|
|
.cpuAddr(cpuAddr),
|
|
.cpuData(cpuData),
|
|
.ncpuAS(ncpuAS),
|
|
.ncpuUDS(ncpuUDS),
|
|
.ncpuLDS(ncpuLDS),
|
|
.cpuRnW(cpuRnW),
|
|
.cpuClk(cpuClk),
|
|
.vramAddr(cpuVramAddr),
|
|
.vramDataOut(cpuVramData),
|
|
.nvramWE(nvramWEpre),
|
|
.nvramCE0(nvramCE0pre),
|
|
.nvramCE1(nvramCE1pre),
|
|
.vidBufSelOut(vidBufSel),
|
|
.ramSize(ramSize)
|
|
);
|
|
*/
|
|
|
|
/*
|
|
cpusnoop cpusnp(
|
|
.nReset(nReset),
|
|
.pixClock(pixClk),
|
|
.seq(vidSeq),
|
|
.cpuAddr(cpuAddr),
|
|
.cpuData(cpuData),
|
|
.ncpuAS(ncpuAS),
|
|
.ncpuUDS(ncpuUDS),
|
|
.ncpuLDS(ncpuLDS),
|
|
.cpuRnW(cpuRnW),
|
|
.cpuClk(cpuClk),
|
|
.vramAddr(),
|
|
.vramDataOut(),
|
|
.nvramWE(),
|
|
.nvramCE0(),
|
|
.nvramCE1(),
|
|
.vidBufSelOut(),
|
|
.ramSize(ramSize)
|
|
);
|
|
*/ |