- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For some time I have been trying to make a simple CGA to VGA converter. I don't need it to be very complicated - it just has to display black and white text.
It is supposed to deinterlace the video signal by storing the whole frame in the first half of the RAM, while the other half is read with a different clock speed and send it to the output. VGA and CGA have completely different pixel clock speeds, so I'm using two PLLs to generate the clock cycles - ~6MHz and ~25MHz
The converter should only be displaying and reading pixels only when it is in a specific part of the frame.
To my knowledge I'm using a Dual Clock RAM, so It should be possible to fit two 128 Kb frames into the block RAM of a Cyclone IV. Hovewer when I try to compile it, it uses a lot more logic elements than it is supposed to. The compilation often hangs for a couple of hours and then crashes. The error I frequently get is:
Sub-system: OPT, File: /quartus/synth/opt/opt_op_decsel.cpp, Line: 2046
One time it finished synthesizing after 1.5 h, it made 218 000 logic elements apart from using the 130Kb of RAM. One time I also got a quartus_map.exe out of memory error as it tried to use 12GB.
I tried using the template of a Simple Dual Port RAM (dual clock), but the problem was the same.
I am quite new to FPGA programming, and I have no idea what might cause this problem as the compiler doesn't show any errors, it just crashes.
Here is the code:
module CGA2VGA2(
input clk,
input rgb,
input cgaVsync,
input cgaHsync,
output reg val,
output reg vgaHsync,
output reg vgaVsync
);
wire cgapxclk;
wire vgapxclk;
reg [8:0] cgahcnt;
reg [8:0] cgavcnt;
reg [9:0] vgahcnt;
reg [9:0] vgavcnt;
reg [6:0] hsyncnt;
reg [1:0] vsyncnt;
reg [16:0] cgafpxcnt;
reg [17:0] vgafpxcnt;
reg f1pxdat [127999:0];
reg f2pxdat [127999:0];
reg parity;
reg frame;
reg vsync, hsync;
reg [1:0] test;
pll PLL (.inclk0(clk), .c0(cgapxclk), .c1(vgapxclk));
always @(posedge cgapxclk) begin
if(cgaHsync && cgahcnt > 320) begin
cgahcnt = 0;
cgavcnt = cgavcnt + 1;
hsync = 1;
end
else begin
cgahcnt = cgahcnt + 1;
hsync = 0;
end
if(!cgaVsync && cgavcnt > 200) begin
cgavcnt = 0;
vsync = 1;
end
else vsync = 0;
if(cgahcnt >=56 && cgahcnt < 376 && cgavcnt >=39 && cgavcnt <239) begin
cgafpxcnt = (cgahcnt-56)*2*(cgavcnt-39);
if(frame) begin
if(parity) f1pxdat[cgafpxcnt] <= rgb;
else f1pxdat[cgafpxcnt+1] <= rgb;
end
else begin
if(parity) f2pxdat[cgafpxcnt] = rgb;
else f2pxdat[cgafpxcnt+1] = rgb;
end
end
end
always @(posedge vgapxclk) begin
if (hsync) begin
vgaHsync = 0;
test = test + 1;
end
if (!vgaHsync && hsyncnt < 96) hsyncnt = hsyncnt + 1;
else begin
vgaHsync = 1;
hsyncnt = 0;
end
if((!vgaHsync && vgahcnt > 320) || vgahcnt >=799) begin
vgahcnt = 0;
vgavcnt = vgavcnt + 1;
if (test[1]) begin
vgaHsync = 0;
end
test = test + 1;
end
else vgahcnt = vgahcnt + 1;
if (vsync) vgaVsync = 0;
if (!vgaVsync && vsyncnt < 2) vsyncnt = vsyncnt + 1;
else begin
vgaVsync = 1;
vsyncnt = 0;
end
if(!vgaVsync && vgavcnt > 200) vgavcnt = 0;
if(vgahcnt >=144 && vgahcnt < 784 && vgavcnt >=75 && vgavcnt <475) begin
vgafpxcnt = (vgahcnt-144)*(vgavcnt-75);
if(!frame) val = f1pxdat[vgafpxcnt[17:1]];
else val = f2pxdat[vgafpxcnt[17:1]];
end
else val = 0;
end
always @(negedge cgaVsync) parity = ~parity;
always @(posedge parity) frame = ~frame;
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I received the reply from our developer today, you have to add the below setting in the QSF file. If the RAM inference is off, the 128K RAM is not fit for generic logic implementation.
set_global_assignment -name AUTO_RAM_RECOGNITION ON
Thanks.
Best regards,
KhaiY
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Can you provide the design.qar for investigation? To create the QAR file click on Project > Archive Project.. What is the software edition (Pro / Standard) and version you are using?
Thanks.
Best regards,
KhaiY
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would suggest that you don't try and code your whole design into a single, flat verilog module.
Break the problem down into submodules.
Your design wants to be oriented around a dual port single writer / single reader memory, so I would follow Altera's coding practice to code that up as a single module.
Then instantiate that in your design, and add the appropriate writer / reader control logic around it.
Trying to code your entire function as one large flat module design is overwhelming the synthesis tool.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I changed the 128000 bit register to a 'simple_dual_port_ram_single_clock' template with data size 1 and address width 17, but the problem remains the same. The conditionals are unique enough, that I don't think it's worth changing them to modules.
module CGA2VGA2(
input clk,
input rgb,
input cgaVsync,
input cgaHsync,
output val,
output reg vgaHsync,
output reg vgaVsync
);
wire cgapxclk;
wire vgapxclk;
reg [8:0] cgahcnt;
reg [8:0] cgavcnt;
reg [9:0] vgahcnt;
reg [9:0] vgavcnt;
reg [6:0] hsyncnt;
reg [1:0] vsyncnt;
reg [16:0] cgafpxcnt;
reg [17:0] vgafpxcnt;
reg parity;
reg frame;
reg vsync, hsync;
reg [1:0] test;
reg f1we, f2we, f1re, f2re;
wire f1out, f2out;
assign val = (f1out&f1re)|(f2out&f2re);
pll PLL (.inclk0(clk), .c0(cgapxclk), .c1(vgapxclk));
RAM f1pxdat (.data(rgb), .read_addr(vgafpxcnt), .write_addr(cgafpxcnt), .we(f1we), .read_clock(cgapxclk), .write_clock(vgapxclk), .q(f1out));
RAM f2pxdat (.data(rgb), .read_addr(vgafpxcnt), .write_addr(cgafpxcnt), .we(f2we), .read_clock(cgapxclk), .write_clock(vgapxclk), .q(f2out));
always @(posedge cgapxclk) begin
if(cgaHsync && cgahcnt > 320) begin
cgahcnt = 0;
cgavcnt = cgavcnt + 1;
hsync = 1;
end
else begin
cgahcnt = cgahcnt + 1;
hsync = 0;
end
if(!cgaVsync && cgavcnt > 200) begin
cgavcnt = 0;
vsync = 1;
end
else vsync = 0;
if(cgahcnt >=56 && cgahcnt < 376 && cgavcnt >=39 && cgavcnt <239) begin
if(frame) begin
f1we = 1;
f2we = 0;
if(parity) cgafpxcnt = (cgahcnt-56)*2*(cgavcnt-39);
else cgafpxcnt = (cgahcnt-56)*2*(cgavcnt-39)+1;
end
else begin
f1we = 0;
f2we = 1;
if(parity) cgafpxcnt = (cgahcnt-56)*2*(cgavcnt-39);
else cgafpxcnt = (cgahcnt-56)*2*(cgavcnt-39)+1;
end
end
else begin
f1we = 0;
f2we = 0;
end
end
always @(posedge vgapxclk) begin
if (hsync) begin
vgaHsync = 0;
test = test + 1;
end
if (!vgaHsync && hsyncnt < 96) hsyncnt = hsyncnt + 1;
else begin
vgaHsync = 1;
hsyncnt = 0;
end
if((!vgaHsync && vgahcnt > 320) || vgahcnt >=799) begin
vgahcnt = 0;
vgavcnt = vgavcnt + 1;
if (test[1]) begin
vgaHsync = 0;
end
test = test + 1;
end
else vgahcnt = vgahcnt + 1;
if (vsync) vgaVsync = 0;
if (!vgaVsync && vsyncnt < 2) vsyncnt = vsyncnt + 1;
else begin
vgaVsync = 1;
vsyncnt = 0;
end
if(!vgaVsync && vgavcnt > 200) vgavcnt = 0;
if(vgahcnt >=144 && vgahcnt < 784 && vgavcnt >=75 && vgavcnt <475) begin
vgafpxcnt = (vgahcnt-144)*(vgavcnt-75);
if(!frame) begin
f1re = 1;
f2re = 0;
end
else begin
f1re = 0;
f2re = 1;
end
end
else begin
f1re = 0;
f2re = 0;
end
end
always @(negedge cgaVsync) parity = ~parity;
always @(posedge parity) frame = ~frame;
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I tried to compile the design, the error Sub-system: OPT, File: /quartus/synth/opt/opt_op_decsel.cpp, Line: 2046 did not occur. Another error occured as below:
Error (170011): Design contains 506287 blocks of type combinational node. However, the device contains only 6272 blocks.
Error 170011 indicates that the Fitter cannot place all blocks of the specified type within target device. The project requires more logic cells than the device has available. To fix error 170011, you have to select a larger device or reduce the number of logic cells in your project.
Can you try to
- unarchive the QAR you have provided earlier, compile and see if you can reproduce the first error or the second error
- In your original design file, clean the project and compile again. To clean the project, click on Project > Clean Project
Thanks.
Best regards,
KhaiY
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After 3h of compilation the error happened again, but I don't think this is a problem. My computer might non be able to deal with this number of logic elements, but that number of them shouldn't be there in the first place.
Is there something wrong with my code? I'm using the default template of dual port RAM, so why would it want to create so many logic cells?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would suggest shrinking the size of your RAMs by a factor of 16 or even 256 and see if you can get the design to compile.
I suspect that Quartus is not recognizing that your RAM module should be implemented with block ram vs discrete registers.
Probably in the way you express the RAM module verilog code (which is not shown).
Then once you get a design that compiles you can see if it is using block rams correctly, or still using registers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I changed the ADDR_WIDTH from 17 to 12. It tried to compile, but it couldnt fit the 16000 logic elements in the device. There were 8254 total registers.
Here is the default template for ram, I'm using:
I'm also attatching the archive file.
// Quartus Prime Verilog Template
// Simple Dual Port RAM with separate read/write addresses and
// separate read/write clocks
module RAM
#(parameter DATA_WIDTH=1, parameter ADDR_WIDTH=17)
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, read_clock, write_clock,
output reg [(DATA_WIDTH-1):0] q
);
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge write_clock)
begin
// Write
if (we)
ram[write_addr] <= data;
end
always @ (posedge read_clock)
begin
// Read
q <= ram[read_addr];
end
endmodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I received the reply from our developer today, you have to add the below setting in the QSF file. If the RAM inference is off, the 128K RAM is not fit for generic logic implementation.
set_global_assignment -name AUTO_RAM_RECOGNITION ON
Thanks.
Best regards,
KhaiY
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks very much for your help! This fixed it!
Now it says that
Error (170048): Selected device has 30 RAM location(s) of type M9K. However, the current design needs more than 30 to successfully fit
Does this mean that this amount of ram will never fit inside a Cyclone IV? Is there a way to optimize it? There is about 14K left and the fitter lists 32 RAM cells.
Sorry, I replied this late, I didn't have time to test this before.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
This error indicates that the design needs more RAMs of a given type than are available on the device. You have to select a larger device, change assignments that are forcing RAMs into this RAM type or change the number of RAMs needed for the design.
Thanks.
Best regards,
KhaiY
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page