Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20691 Discussions

Problem with indexing a large register.

kwiorek
Beginner
1,115 Views

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

 

0 Kudos
1 Solution
KhaiChein_Y_Intel
955 Views

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

View solution in original post

12 Replies
KhaiChein_Y_Intel
955 Views

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

0 Kudos
kwiorek
Beginner
955 Views

Here is the QAR file. I have the Lite version, as I'm doing this just as a hobby and I don't plan to buy the paid license.

0 Kudos
ak6dn
Valued Contributor III
955 Views

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.

0 Kudos
kwiorek
Beginner
955 Views

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

 

0 Kudos
KhaiChein_Y_Intel
955 Views

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

  1. unarchive the QAR you have provided earlier, compile and see if you can reproduce the first error or the second error
  2. In your original design file, clean the project and compile again. To clean the project, click on Project > Clean Project

 

 

Thanks.

Best regards,

KhaiY

0 Kudos
kwiorek
Beginner
955 Views

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?

0 Kudos
ak6dn
Valued Contributor III
955 Views

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.

0 Kudos
kwiorek
Beginner
955 Views

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

 

0 Kudos
KhaiChein_Y_Intel
956 Views

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

kwiorek
Beginner
955 Views

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.

0 Kudos
KhaiChein_Y_Intel
955 Views

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

kwiorek
Beginner
955 Views

Thanks!

0 Kudos
Reply