Hi TomS_,
No, I didn't forget about you. I looked at your code and it is huge. So, what I would like to do is attack your problem with optimization techniques with tiny code changes here and there.
1. First, make sure your 'osc_40mhz' is wired to a global clock input on the CPLD.
2. Your clock output pins.
output logic eth_clk,
output logic cpu_clk,
output logic timer_clk,
Because they come from 1 counter, make sure all 3 are located on 3 adjacent IOs on the CPLD. Make sure those 3 come from 1 block inside the CPLD. This will minimize routing the output LCELL across the CPLD fuse map.
3. Ok, everywhere you used a single negedge for the 40MHz in your code. Some you have a 'or negedge n_reset'. Note that only if your reset pulse will be less than 1/40millionth of a second, you can comment this out saving some routing. If you want the async reset to be wired as such in the CPLD, you need to tell quartus to use your reset signal as a global reset signal. With a CPLD, you may be forced to use a specific dedicated input for this functionality. Specifying in code and using a global reset input line uses a dedicated net on the CPLD fabric saving on the logic fuse map. (Note that if you do this wrong with, Quartus will still compile and somewhere hiding in the compilation report it will say something like 'Could not use dedicated reset line for n_reset input. Global lowered to a standard net')
4. Since output 'n_berr_drv' is so closely tied to:
output logic eth_clk,
output logic cpu_clk,
output logic timer_clk,
it's output should be adjacent to them.
(Do not touch this for now if it works, this will only save 1-4 cells it you truly need that)
5. Line 373 - 'always_ff @(posedge cpu_clk) begin'
Line 374 - 383 (your clocked logic block)
(Do not touch this for now if it works, this will only save 1-4 cells it you truly need that)
You can change lines 373 to @(negedge osc_40mhz) and stuff lines 374 through 383 inside this 'if'.
if (!cpu_clk && eth_clk) begin
lines 374-383
end
All I have done here is place your entire project on the (negedge 40Mhz), and use the cpu_clk and eth_clk as an enable for that timeout counter. You may need to fiddle with the '!'. This one is to prevent Quartus from having to route a new custom clock line for the clock's output LCELL to your 2 bit timeout counter. Also having everything in a single clock domain really helps Quartus optimize and minimize you code.
With these changes, Quartus compiling with setting 'Optimize Area' mode, you will still get a good FMAX and minimal size. The only way to further shrink the size is to ask Quartus to generate a custom pin map for you. But, that pin map will be kinda random.