Video Ram, multiple clock domains FPGA
Posted: Tue Dec 28, 2021 2:47 am
Hey Guys,
Been working on an FPGA Video controller for my FPGA project and one of my big struggles has been the Video Ram. Running real time assignments giving the CPU priority to the ram works great, apart from the video artifacts, especially during large writes.
The ram is 10ns, the Video clock is at 25mhz and the system clock is 8mhz. Based upon the speed of the ram there should be way more than enough time to fulfill the requests for both the video driver and the cpu within their respective clocks.
Below is a snippet of code for the video ram with the topmost section containing the realtime assignments that are working, followed by the code of one my latest of many failed attempts to share the memory between the two clocks. Of note the main clk input is 100mhz (10ns per cycle) and the sclk is 8mhz with the vclk @ 25mhz. Also, while this attempt at sharing is the one I'm least proud of, it actually produced the best results and was able to return ****somewhat**** valid data to the video driver, but as usual, cpu reads and writes were non existent.
Additionally, I could likely use block ram on the FPGA with better results, but I'd prefer the sram as there is enough to support full bitmap at 640*480. I also don't want to use DMA as I don't want to sacrifice the CPU speed.
Any help would be greatly appreciated.
Been working on an FPGA Video controller for my FPGA project and one of my big struggles has been the Video Ram. Running real time assignments giving the CPU priority to the ram works great, apart from the video artifacts, especially during large writes.
The ram is 10ns, the Video clock is at 25mhz and the system clock is 8mhz. Based upon the speed of the ram there should be way more than enough time to fulfill the requests for both the video driver and the cpu within their respective clocks.
Below is a snippet of code for the video ram with the topmost section containing the realtime assignments that are working, followed by the code of one my latest of many failed attempts to share the memory between the two clocks. Of note the main clk input is 100mhz (10ns per cycle) and the sclk is 8mhz with the vclk @ 25mhz. Also, while this attempt at sharing is the one I'm least proud of, it actually produced the best results and was able to return ****somewhat**** valid data to the video driver, but as usual, cpu reads and writes were non existent.
Additionally, I could likely use block ram on the FPGA with better results, but I'd prefer the sram as there is enough to support full bitmap at 640*480. I also don't want to use DMA as I don't want to sacrifice the CPU speed.
Any help would be greatly appreciated.
Code: Select all
`timescale 1ns / 1ps
module vBuffer(
input clk,
output wire [18:0] sram_a,
inout wire [7:0] sram_d,
output wire sram_wen,
output wire sram_cen,
input wire [18:0] syAdr,
inout wire [7:0] datIO,
input wire syCs,
input wire syRw,
input wire [18:0] vAdr,
input wire vCs);
assign sram_a = (!syCs) ? syAdr : vAdr;
assign sram_cen = (!syCs || !vCs) ? 0 : 1;
assign sram_wen = (!syCs && !syRw) ? 0 : 1;
assign datIO = (!syCs && !syRw) ? 8'bZZZZZZZZ : sram_d;
assign sram_d = (!syCs && !syRw) ? datIO : 8'bZZZZZZZZ;
/*
module vBuffer(
input clk,
input wire vClk,
input wire sClk,
output wire [18:0] sram_a,
inout wire [7:0] sram_d,
output wire sram_wen,
output wire sram_cen,
input wire [18:0] syAdr,
inout wire [7:0] datIO,
input wire syCs,
input wire syRw,
input wire [18:0] vAdr,
output reg [7:0] vDat,
input wire vCs);
reg vidEvt = 0;
reg syReadEvt = 0;
reg syWriteEvt = 0;
reg vidLastClk = 0;
reg syLastClk = 0;
reg vidRead = 0;
reg syWrite = 0;
reg syRead = 0;
reg [18:0]_syAdr;
reg [7:0] _syDatIn;
reg [7:0] _syDatOut;
assign sram_a = (syWrite || syRead) ? _syAdr : vAdr;
assign sram_d = (syWrite) ? _syDatIn : 8'bZZZZZZZZ;
assign sram_cen = (syWrite || syRead || vidRead) ? 0 : 1;
assign sram_wen = (syWrite) ? 0 : 1;
assign datIO = (!syCs && syRw) ? _syDatOut : 8'bZZZZZZZZ;
always @(posedge clk) begin
if (vidRead) begin
vDat <= sram_d;
vidRead <= 0;
end
else if (syRead) begin
_syDatOut <= sram_d;
syRead <= 0;
end
else if (syWrite) syWrite <= 0;
if(~vidLastClk && vClk && vidEvt) vidRead <= 1;
else if (syLastClk && !sClk && syWriteEvt) begin
syWrite = 1;
syLastClk <= sClk;
end
else if (!syLastClk && sClk && syReadEvt) begin
syRead = 1;
syLastClk <= sClk;
end
else begin
syLastClk <= sClk;
end
vidLastClk <= vClk;
end
always @(posedge vClk) begin
if (!vCs) vidEvt <= 1;
else vidEvt <= 0;
end
always @(sClk) begin
if (!syCs && syRw && sClk) begin
_syAdr <= syAdr;
syWriteEvt <= 0;
syReadEvt <= 1;
end
else if (!syCs && !syRw && !sClk) begin
_syAdr <= syAdr;
_syDatIn <= datIO;
syReadEvt <= 0;
syWriteEvt <= 1;
end
else begin
syReadEvt <= 0;
syWriteEvt <= 0;
end
end
*/
endmodule