[myhdl-list] List of Signals == Memory
Brought to you by:
jandecaluwe
|
From: Christopher L. F. <cf...@uc...> - 2008-02-04 08:20:12
|
In this newsgroup a "List of Signals" appears to be a common theme or
misunderstanding. I think it is a "natural" Pythonic usage of lists as
general containers, to group items, build structures, etc.
With the current implementation there are some limitations to using a
list of signals. Example the "list syntax" cannot be used in the
generator code. This seems to break a very natural way of writing HDL
in python.
The last 2 MyHDL projects that I did I ran into exactly this issue. I
used a "List of Signals" to logically group related (but separate)
signals. But I had to go and rewrite the MyHDL code once I tried to
convert the code to Verilog/VHDL. The second project I have not gotten
working yet (still converting) and the first project I had to throw away
modularity and simply type out sig0, sig1, sig2, ...
I usually end up using "List of Signals" because I am
1. Trying to create parameter modules
2. Logically organize signals
3. I am lazy, don't want to type "din0, din1, din2, ..."
and maintain
I think the main issue is that a "List of Signals" is preferred to be
converted to a memory. I don't know if this always makes sense because
a Signal is used as 'reg' and 'wire'. I have used Verilog 2D vectors to
represent memories but also a collection of N 32bit buses.
Second issue would be loop unrolling.
Possible resolutions (or at least start dialog to educate me)
1. Create a new type 'Memory' that is simply a new class
that inherits a 'Signal'. This way simulation will not
change because 'Memory' will be treated the same as a
'Signal'. And the conversion can simply identify a memory
type. A "List of Signals" will not be converted to a memory
structure, only a 'List of Memory' will be converted to a
Verilog/VHDL memory structure.
2. The MyHDL to Verilog/VHDL should unroll the loops.
a. This is what the synthesis tool will eventually do anyway
b. Allow list syntax in generator code
Pros/Cons:
Pros - Hopefully this was somewhat covered above.
1. More flexible (natural?) use of a "List of Signals"
2. There maybe more special cases for memories that the new
type will help handle. Also memories are commonly used to
simulate an existing memories functionality. Don't actually
need the conversion.
Cons
1. Not necessarily a minimalistic approach (i.e. adding a new type)
Example of a previous post (Subj: ListElementNotUnique error 5/24/2006)
> signal_list = [Signal(intbv(0)[WIDTH:]) for i in range(NUMBER)]
> insts = [module_name(signal_list[i]) for i in range(NUMBER)]
> @always(clk.negedge)
> def select_best():
> """Compare values and select the best one"""
> best=0
> for nr in range(NR_REGS):
> if signal_list[nr] > signal_list[best]:
> best=nr
>
> max.next = best
With the current implementation the above will not work. In the
original thread Jan gave a good explanation why it currently does not
work and some examples of how "List of Signals" can be used. But my
thought is that the above is an common approach and maybe it should work.
Now the above example would still not work with my proposed changes but
I think it would be closer. First the "List of Signals" would not be
convert to memories (no confusion what it should be) second the list
syntax can be used in the generator code. The above loop would not work
for the same reason as it would not in Verilog. The indices in the loop
are not static so the loop cannot be unrolled for a fully parallel
implementation. But it could be change to the following.
> din = [Signal(intbv(0)[WIDTH:]) for i in range(NUMBER)]
> dout = Signal(intbv(0)[WIDTH:])
> ...
> def top(dout, din, clk, WIDTH=8):
> max = [Signal(intbv(0)[WIDTH:]) for i in range(len(din))]
> max[0] = din[0] # assign statement
>
> @always_comb
> def compare():
> for i in range(NR_REGS-1):
> if max[i] > din[i+1]:
> max[i+1].next = max[i]
> else:
> max[i+1].next = din[i+1]
>
> @always(clk.negedge)
> def dout_reg():
> dout.next = max[-1]
>
> return dout_reg, compare
Now the above unrolled should provide a parallel implementation,
cascaded compares (basically Jan's original solution, just different).
This is similar to how I may write Verilog, one behavioral block for
combinational logic (if it complicated) and a behavioral block for
sequential.
I doubt this would be a simple change(?) because the din would have to
be converted to din_0, din_1, ... din_NUMBER, and this would have to be
included in declarations, ports, etc (same for any list of signals).
There have also been some recent posts with similar questions/issues.
Thanks
|