2

I am creating a custom CPU and would like it to be programmable on the fly instead of hard coded in VHDL. The issue I am having is that without initial code for the CPU to run, ISE will trim large amounts of my logic away. I have tried using the 'S' attribute to declare my signals and variables as 'not trimmable', but that does not work on all of the signals. I have also tried setting the keep hierarchy option in XST, but even that fails sometimes (complains that there is a conflict with the KEEP settings and will trim anyway). Is there a way for me to tell ISE to not trim anything at all without having to create a default program that runs through every opcode?

Here is one of the errors I am seeing:

WARNING:Xst:638 - in unit cpu_instructor_copy Conflict on KEEP property on signal brain.current_opcode<0> and brain.stack_pointer<14> brain.stack_pointer<14> signal will be lost.

Without the S attribute, the stack_pointer will just get removed.

I have the following at the top of my 'brain' process

variable stack_pointer : integer range 0 to (2**mem_addr'length) - 1 := stack_origin;
attribute S : string;
attribute S of stack_pointer : variable is "YES";

Thank you in advance!

Edit: Here is the actual code (no attributes in it currently as those are on my personal test copy)

Edit 2: The problem was fixable by changing my program from a constant to a signal, adding a new process that could 'program' the CPU with serial (at least that's what the design thinks), and setting the Map process to not trim unconnected signals. I will post the code a little later. Thank you all!!

Proto
  • 23
  • 4
  • 3
    You need to make sure the logic you want to keep is actually used. Expose some interface to the instruction memory to the outside, and it won't get cut out. – darron Nov 21 '13 at 03:51
  • Either to the outside, or initialise the instruction memory with test code (write a suitable init function for the purpose) –  Nov 21 '13 at 10:20
  • @BrianDrummond I was afraid that was going to be the only acceptable answer. Is init code like that normal for CPUs in an FPGA? – Proto Nov 21 '13 at 13:39
  • @darron Thanks for the info. It rather sucks that I can't just disable trimming. Any idea why trimming can't just be disabled? – Proto Nov 21 '13 at 13:40
  • Not all FPGAs support such an init; Xilinx is OK with it, and I see you're using XST... –  Nov 21 '13 at 13:47
  • If there's no way to get code _into_ the thing, and no way for results to get out, it's entitled to remove it. Where is your code stored? – pjc50 Nov 21 '13 at 15:26
  • 3
    Proto: Because a very basic function of the synthesis tool is to simplify the logic. There are inputs, some process, and output. If there's something in the process that cannot affect the output, then it's completely pointless and SHOULD be removed. It's like telling someone to write a three page paper, let nobody know or witness it, then erase all but the first sentence. You need to give meaning to the logic being simplified away by having it actually affect the result. This is usually not hard to do. You could add a function that returns the checksum of all memory, for instance. – darron Nov 21 '13 at 19:39
  • IMO, without knowing the whole block, it is hard to defend or criticize the behavior of the XST. One important issue I see here is that you are using a variable, which is kind of odd for me to understand. Why do you want your stack pointer to be of the type Variable? Is your CPU asynchronous? Also, one of the things I have learned about issues like this is the problem with simulation models of designs where all signals are given a default value to simplify the simulation, which causes the designer to believe their code is error free, but then they see the problem during synthesis. – FarhadA Nov 22 '13 at 12:00
  • @darron I do understand that XST wants to get rid of areas of code that cannot be reached. The problem I have with it is that there is no way of knowing what areas will and will not be reached once the user has programmed the 'CPU'. If the uploaded program does not use division, that's fine. But if it does use division, then I don't want XST to optimize it away. I was hoping that the 'CPU' program space could be left empty, and then programmed later over USB. – Proto Nov 22 '13 at 13:49
  • @FarhadA I make use of variables anytime I have something that does not need to be read by any other processes. My 'CPU' is a very, very simple one in that it does not have separate processes for the various parts. It has one big process that checks the current opcode and does whatever it needs to based on that opcode. I was of the understanding that using variables in a case like this was okay. Is that not correct? (I'm completely self taught with FPGAs, so I'm surely making mistakes!) – Proto Nov 22 '13 at 13:52
  • Proto: The program memory must be ROM and can't be updated later? Just add an interface that allows outside writes into program memory (some kind of debug port, SPI, whatever) and the entire problem goes away. If the memory can change, then it won't get removed. That's how you usually solve this problem. – darron Nov 22 '13 at 14:49
  • @darron: I have it as ROM now since the class has not gotten to USB/serial yet. I haven't even thought of changing it to a signal and adding a process that can modify the contents. I made an assumption that XST would trim no matter what in this case. I will give this a try when I get home tonight. Thank you very much! – Proto Nov 22 '13 at 15:20
  • @pjc50 The code is [here](https://github.com/Unallocated/FPGA/blob/cpu/cpu_instructor_copy.vhd) – Proto Nov 22 '13 at 17:00

1 Answers1

0

You can prevent trimming with an option on the Map process properties. In ISE, expand the 'Implement Design' section, and right click 'Map' and select 'Process Properties'

Uncheck the option for 'Trim Unconnected Signals' (-u). Click the help button for more information on all the options displayed here.

From the help:

Trim Unconnected Signals

Specifies whether or not to trim unconnected components and nets from the design before mapping occurs. Leaving this option blank is useful for estimating the logic resources required for a design and for obtaining timing information on partially finished designs. When implementing an unfinished design, set this property to False (checkbox is blank) to map unconnected components and nets.

By default, this property is set to True (checkbox is checked), and unconnected components and nets are trimmed.

Marcus10110
  • 589
  • 3
  • 13