Help with ISE (multi-source in unit error)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View

     I'm pretty new to verilog and I am trying to write code to compute
a mean and store it in RAM.  I update the ram each time a new sample
comes in and thus the ram becomes my second addend. Here is a bit of
the code.  Why am I getting multi-source in unit on cal_ram_di?

always @(posedge clk)
    if(~done & stepCnt == 0)
        if(cal_cnt == 0)
            addend1 <= {8'h00, samp12}; //pad with zeros to the left, new sample
to add to running sum
            addend2 <= cal_ram_do[20:0];    //the current running sum for the
            gotoffset <= 0;
        else if(cal_cnt == 1)
            if(sampCtr == 0)
                cal_ram_di[20:0] <= addend1; //this is the first sample
                cal_ram_we <= 1; //assert the write enable so we can latch the data
in the RAM
                cal_ram_di[20:0] <= addend1 + addend2; //every other sample
                cal_ram_we <= 1;
        else if(cal_cnt == 2)
            if(sampCtr == 511)
                meanVal <= cal_ram_di[20:9]; //we have monitored for 512 samples so
divide by 2^9 (512) --- leave this as di.
        else if(cal_cnt == 3)
            if(sampCtr == 511) //we have computed sums for all 512 samples so
compute the offset
                cal_ram_di[28:0] <= {(meanVal-12'h800), 16'h0000, 1'b0}; //put the
offset in the right spot because if it is not there i can't do the
offset subtraction the same the whole time
                cal_ram_we <= 1; //assert ram write enable and latch the data
                gotoffset <=1;

Re: Help with ISE (multi-source in unit error)

Quoted text here. Click to load it

Are you sure this is all the code which assigns to cal_ram_di? What
you show is a single always block so it's difficult to get a
multi-source out of it. Check where else you're using cal_ram_di to
see if you're declaring it as input or whether you're assigning to it

Another comment is that you can change the "if (cal_cnt==0) to a case
statement which might give you better performance.

Re: Help with ISE (multi-source in unit error)
That is only one of my always blocks that works with cal_ram_di.  I
have two others but they are based ont the conditions if(~done
&stepCnt==1) and if(~done & stepCnt ==2) that what is causing the
problem??  If so how do I fix that?
mk wrote:
Quoted text here. Click to load it

Re: Help with ISE (multi-source in unit error)
Quoted text here. Click to load it
Probably. The synthesis tool probably found an occassion where two or
more if-conditions are possible met at the same time, hence the signal
is assigned in two different places, and the tool doesn't know which of
the assigments is to be carried out.

Quoted text here. Click to load it
As a general rule: Each signal should only be assigned in one single
always-block, or process-construct in VHDL, not in several, or you
almost always run into the kind of problem you're having now.

You need to have ONE block of instructions that covers the assignment of
"cal_ram_di" for all possible cases, and "cal_ram_di" should only be
read in other always-blocks, never be assigned.

Maybe a little insight into synthesis tools might help here. What a
synthesis tool does (after checking the syntax and so on) is search your
code for certain templates. These templates you can find in the
ISE-documentation. For example, if the tool finds something like

counter <= counter + 1

it recognizes this as a counter (it "infers" a counter), determines the
bit width and then picks a more or less predefined schematic for a
x-bit-upward-counter out of a library that comes with the tool. That is
a schematic of interconnected gates or whatever that in combination make
up a counter.

Just like there are templates for counters, there are templates for
things such as state machines, multiplexers, multipliers and so on. If
you look at the synthesis report, you can see a table of all the things
the tool found in your code.

Another important template is the one for flip-flops and registers.
Basically, every signal that is assigned inside a clocked process in
VHDL or a always @(posedge clk)-block in Verilog infers a flip-flop (if
it's a single-bit-signal) or a set of flip-flops called register (if
it's several bits wide).

The code snippet you posted basically (don't really know Verilog) looks
to me like a register with an enable, i.e. the register transfers the
input value to the output if (~done & stepCnt == 0) AND (cal_cnt == 0).
The output of the register is called "cal_ram_di". What you probably did
is create several registers with different enable signals (one is
enabled when ~done & stepCnt == 1, one when ~done & stepCnt == 2 and so
on), and all of their outputs are assigned to the same signal
"cal_ram_di". Now what happens if in two different always-blocks
different values are assigned to "cal_ram_di"? Which should it really
use? That's the problem you're having.

So, to sum it up:

1. Assignments for ONE signal should only happen in ONE place (ONE
always-block, process, whatever)
2. Have a look at the synthesis report, see what ISE finds in your code,
and try to make sense of it.
3. Have a look at the RTL-schematic ISE produces to get a feeling what
the hardware you get in the end looks like. You might start with some
simple circuits, just to see what combinations of flip-flops, gates and
so on gets synthesized when you write your code this way or the other.

Hope that helps,

Re: Help with ISE (multi-source in unit error)

Quoted text here. Click to load it

If only synthesis tools were that smart. Independent of the condition
the register is assigned, you will get this error if two always blocks
assign a register. Just don't do it. One solution is to move all the
assignment into a combinational always block ie one which generates
the D input of the flops to be assigned. Then you can add multiple
independent if conditions more easily and assign the d input to the
register in a clocked always block.

always @(*)
    if (some condition)
        cal_ram_di_d = first;
    if (some other condition)
        cal_ram_di_d = second;

always @(posedge clk)
    cal_ram_di <= cal_ram_di_d;

Re: Help with ISE (multi-source in unit error)
That fixed the problems I was having and cut my code by about 50 lines.
Quoted text here. Click to load it

Site Timeline