mirror of
https://github.com/techav-homebrew/SE-VGA.git
synced 2024-09-26 23:55:12 +00:00
108 lines
4.0 KiB
Systemverilog
108 lines
4.0 KiB
Systemverilog
/******************************************************************************
|
|
* SE-VGA
|
|
* CPU Bus Snoop
|
|
* techav
|
|
* 2021-04-06
|
|
******************************************************************************
|
|
* Watches for writes to frame buffer memory addresses and copies that data
|
|
* into VRAM
|
|
*****************************************************************************/
|
|
|
|
module cpusnoop (
|
|
input wire nReset, // System Reset signal
|
|
input wire pixClock, // 25.175MHz Pixel Clock
|
|
input logic [2:0] sequence, // Sequence count (low 3 bits of hCount)
|
|
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 wire cpuClk, // CPU Clock
|
|
output logic [12:0] vramAddr, // VRAM Address Bus
|
|
inout logic [7:0] vramData, // VRAM Data Bus
|
|
output wire nvramWE, // VRAM Write strobe
|
|
);
|
|
|
|
// framebuffer address (with 4MB RAM installed): 0x3FA700 - 0x3FFFFF
|
|
|
|
wire pendWriteLo; // low byte write to VRAM pending
|
|
wire pendWriteHi; // high byte write to VRAM pending
|
|
logic [12:1] addrCache; // store address for cpu writes to framebuffer
|
|
logic [7:0] dataCacheLo; // store data for cpu writes to low byte
|
|
logic [7:0] dataCacheHi; // store data for cpu writes to high byte
|
|
|
|
// when cpu addresses the framebuffer, save the address
|
|
always @(negedge ncpuAS or negedge nReset) begin
|
|
if(nReset == 1'b0) begin
|
|
addrCache <= 16'h0;
|
|
end else begin
|
|
if(cpuAddr >= 24'h3FA700 && cpuAddr < 24'h400000) begin
|
|
addrCache[12:0] <= cpuAddr - 16'hA700;
|
|
end
|
|
end
|
|
end
|
|
|
|
// when cpu addresses the framebuffer, save high byte
|
|
always @(negedge ncpuUDS or negedge nReset) begin
|
|
if(nReset == 1'b0) begin
|
|
dataCacheHi <= 8'h0;
|
|
end else begin
|
|
if(cpuAddr >= 24'h3FA700 && cpuAddr < 24'h400000 && cpuRnW == 1'b0) begin
|
|
dataCacheHi <= cpuData[15:8];
|
|
end
|
|
end
|
|
end
|
|
|
|
// when cpu addresses the framebuffer, save low byte
|
|
always @(negedge ncpuUDS or negedge nReset) begin
|
|
if(nReset == 1'b0) begin
|
|
dataCacheLo <= 8'h0;
|
|
end else begin
|
|
if(cpuAddr >= 24'h3FA700 && cpuAddr < 24'h400000 && cpuRnW == 1'b0) begin
|
|
dataCacheLo <= cpuData[7:0];
|
|
end
|
|
end
|
|
end
|
|
|
|
// set pending flags for cpu accesses & clear when that cycle comes back around
|
|
always @(negedge pixClock or negedge nReset) begin
|
|
if(nReset == 1'b0) begin
|
|
pendWriteLo <= 1'b0;
|
|
pendWriteHi <= 1'b0;
|
|
end else begin
|
|
if(cpuAddr >= 24'h3FA700 && cpuAddr < 24'h400000 && cpuRnW == 1'b0) begin
|
|
if(ncpuUDS == 1'b0) begin
|
|
pendWriteHi <= 1'b1;
|
|
end
|
|
if(ncpuLDS == 1'b0) begin
|
|
pendWriteLo <= 1'b1;
|
|
end
|
|
end else begin
|
|
if(sequence == 3'h1) begin
|
|
pendWriteLo <= 1'b0;
|
|
end
|
|
if(sequence == 3'h2) begin
|
|
pendWriteHi <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
always_comb begin
|
|
vramAddr[12:1] <= addrCache[12:1];
|
|
if(pendWriteLo == 1'b1 && sequence == 3'h1) begin
|
|
vramAddr[0] <= 1'b0;
|
|
nvramWE <= 1'b0;
|
|
vramData <= dataCacheLo;
|
|
end else if(pendWriteHi == 1'b1 && sequence = 3'h2) begin
|
|
vramAddr[0] <= 1'b1;
|
|
nvramWE <= 1'b0;
|
|
vramData <= dataCacheHi;
|
|
end else begin
|
|
vramAddr[0] <= 1'b0;
|
|
nvramWE <= 1'b1;
|
|
vramData <= 8'bZ;
|
|
end
|
|
end
|
|
endmodule |