diff --git a/primitives/primitives.sv b/primitives/primitives.sv index 7c145a3..769dc5d 100644 --- a/primitives/primitives.sv +++ b/primitives/primitives.sv @@ -45,8 +45,29 @@ module mux8x1 ( input logic[2:0] select, output wire out ); - always_comb begin - out <= in[select]; + assign out <= in[select]; +endmodule + +// basic 8-to-1 mux with transparent output latch +module mux8x1latch ( + input logic[7:0] in, + input logic[2:0] select, + input wire clock, + input wire nReset, + output reg out +); + wire muxOut; + mux8x1 mux (in,select,muxOut); + + // transparent latch -- when clock is low, output will + // follow the output of the mux. When clock is high, + // output will hold its last value. + always @(clock or nReset or muxOut) begin + if(nReset == 1'b0) begin + out <= 1'b0; + end else if(clock == 1'b0) begin + out <= muxOut; + end end endmodule diff --git a/se-vga.sv b/se-vga.sv index 3b0c830..2d87f51 100644 --- a/se-vga.sv +++ b/se-vga.sv @@ -33,15 +33,64 @@ logic [9:0] vCount; wire hActive; wire hSEActive; -logic [7:0] vidVramData; +//logic [7:0] vidVramData; logic [12:0] vidVramAddr; +//logic [7:0] cpuVramData; +logic [12:0] cpuVramAddr; // link module that generates all our timing signals -vgagen vgatiming(nReset,pixClk,hCount,hActive,hSEActive,nhSync,vCount,vActive,vSEActive,nvSync); -// link module that fetches & outputs video data -vgaout vidvram(pixClock,nReset,hCount,vCount,hSEActive,vSEActive,vidVramData,vidVramAddr,nvramOE,vidOut); -// link module that handles cpu writes +vgagen vgatiming( + .nReset(nReset), + .pixClk(pixClk), + .hCount(hCount), + .hActive(hActive), + .hSEActive(hSEActive), + .nhSync(nhSync), + .vCount(vCount), + .vActive(vActive), + .vSEActive(vSEActive), + .nvSync(nvSync) +); +// link module that fetches & outputs video data +vgaout vidvram( + .pixClock(pixClk), + .nReset(nReset), + .hCount(hCount), + .vCount(vCount), + .hSEActive(hSEActive), + .vSEActive(vSEActive), + .vramData(vramData), + .vramAddr(vidVramAddr), + .nvramOE(nvramOE), + .vidOut(vidOut) +); + +// link module that handles cpu writes +cpusnoop cpusnp( + .nReset(nReset), + .pixClock(pixClk), + .sequence(hCount[2:0]), + .cpuAddr(cpuAddr), + .cpuData(cpuData), + .ncpuAS(ncpuAS), + .ncpuUDS(ncpuUDS), + .ncpuLDS(ncpuLDS), + .cpuRnW(cpuRnW), + .cpuClk(cpuClk), + .vramAddr(vramAddr), + .vramData(cpuVramData), + .nvramWE(nvramWE) +); + +always_comb begin + // vramAddr muxing + if(.nvramWE == 1'b0) begin + vramAddr <= cpuVramAddr; + end else begin + vramAddr <= vidVramData; + end +end endmodule \ No newline at end of file diff --git a/vgaout.sv b/vgaout.sv index e08b1d7..4a37009 100644 --- a/vgaout.sv +++ b/vgaout.sv @@ -25,8 +25,25 @@ module vgaout ( reg [7:0] rVid; wire vidMuxOut; wire vidActive; // combined active video signal +wire vidMuxClk; // latch mux output just before updating rVid -mux8x1 vidOutMux(rVid[7:0],hCount[2:0],vidMuxOut); +// select bits 0..7 from the vram data in rVid, and latch if +// vidMuxClk goes high +mux8x1latch vidOutMux(rVid,hCount[2:0],vidMuxClk,nReset,vidMuxOut); + +// vidMuxClk should be low during sequence 0..6, and high for 7 +// this may lead to a race condition trying to change the mux +// before the output is latched. The alternative is to latch on +// the rising edge of pixClock during sequence 7, but then we may +// have a race condition with the data coming in from VRAM. +// What we really need is a half clock delay :-/ +always_comb begin + if(hCount[2:0] == 3'd7) begin + vidMuxClk <= 1'b1; + end else begin + vidMuxClk <= 1'b0; + end +end // latch incoming vram data on rising clock and sequence 7 always @(posedge pixClock or negedge nReset) begin