generic serial to parallel IO module

E

eddie

Guest
Hi Group,

I'm trying to find a way to input and output multiple m bit signals
from an FPGA, where m is a very large number. The design is a (not
quite) serial to parallel in and a parallel to serial out module.

let's say that input is a 32 bit wide signal, inputOne is a 256 bit
wide signal.
inputCounter counts from 0 to 7, inputNumber counts from 0 to 3.
inputCounter counts if input is enabled. inputNumber counts if
inputCounter reaches 7 and input is enabled.

My question is whether I can provide a generate statement or
synthesisable function to provide the following: arbitrary numbers of
input/output groups, with an arbitrary serial width, and an arbitrary
parallel width.
I'd like to drive logic creation with the following numbers:
width of parallel bus,
width of 'serial' bus,
number of inputs,
number of outputs,
number of input serial 'slices'
number of output serial 'slices'
number of bits for inputNumber, inputGroup, outputNumber, outputGroup
counters


Is there a way of writing inputOne( variable1 downto variable2 ) <=
input ?
Can I find a way to produce the following in some kind of code
generating loop?
Are there guidelines for writing synthesisable functions, or is this
vendor specific in the main?

thanks
Edward Watts



PS Currently my code looks something like:

process( clk )
--reset code here
if clk'event and clk = '1' then

if some_IO_condition = '1' then
-- do stuff

elsif inputing = '1' then

if inputNumber = "00" then

if inputCounter = "000" then
inputOne( 31 downto 0 ) <= input;

elsif inputCounter = "001" then
inputOne( 63 downto 32 ) <= input;

--...
elsif inputCounter = "111" then
inputOne( 255 downto 224 ) <= input;

end if;

elsif inputNumber = "01" then

if inputCounter = "000" then
inputTwo( 31 downto 0 ) <= input;
elsif inputCounter = "001" then
--...
end if;

elsif inputGroup = "10" then
--...
elsif inputGroup = "11" then
--...
end if;
elsif outputting = '1' then

if outputNumber = "00" then

if outputCounter = "000" then
output_internal <= output( 31 downto 0 );

elsif outputCounter = "001" then
--...
end if;
end if;
end if;
end if;
end process;
 
eddie wrote:
Hi Group,

...
My question is whether I can provide a generate statement or
synthesisable function to provide the following: arbitrary numbers of
input/output groups, with an arbitrary serial width, and an arbitrary
parallel width.
I'd like to drive logic creation with the following numbers:
width of parallel bus,
width of 'serial' bus,
number of inputs,
number of outputs,
number of input serial 'slices'
number of output serial 'slices'
number of bits for inputNumber, inputGroup, outputNumber, outputGroup
counters


Is there a way of writing inputOne( variable1 downto variable2 ) <=
input ?
Can I find a way to produce the following in some kind of code
generating loop?
Are there guidelines for writing synthesisable functions, or is this
vendor specific in the main?

If your arbitrary numbers are generics, that is, they are fixed at
synthesis time, then generate statements are perfect for what you
describe. For example, create a generic loop for the number of input slices:
slice_g: for i in 0 to slices-1 generate
slice_p: process(...)
begin
inputOne(width*(i+1)-1 downto width*i) <= whatever;



...
if inputNumber = "00" then

if inputCounter = "000" then
inputOne( 31 downto 0 ) <= input;

elsif inputCounter = "001" then
inputOne( 63 downto 32 ) <= input;

--...
elsif inputCounter = "111" then
inputOne( 255 downto 224 ) <= input;

end if;

elsif inputNumber = "01" then

if inputCounter = "000" then
inputTwo( 31 downto 0 ) <= input;
elsif inputCounter = "001" then
--...
end if;
Strictly speaking, this really isn't an 'elsif inputNumber', since for
example the signal inputOne is only altered in one case. That is, an
if...elsif... implements a priority encoding. But in your situation,
there is no priority. So it really should be
if inputNumber = "00" then
...
end if;
if inputNumber = "01" then
...
end if;
On the other hand, I suspect the synthesis tools will automatically
simplify this correctly, so it is probably just an issue of writing the
code in a way that clearly describes what is happening.
 
eddie wrote:

My question is whether I can provide a generate statement or
synthesisable function to provide the following: arbitrary numbers of
input/output groups, with an arbitrary serial width, and an arbitrary
parallel width.
Synthesizable *process*, yes.
You can generate processes as Duane outlined
or declare complex register structures
in a single process.

Is there a way of writing inputOne( variable1 downto variable2 ) <=
input ?
Not exactly, but
I can declare internal register structures
of arbitrary complexity using generic or
packaged constants for dimensions. For example:

-- Make and init 6 sets of 32 bit counter/register pairs
process (sys_clk, reset) is
-- 32 bit register
subtype stat_reg_t is unsigned (cnt_len-1 downto 0);
-- counter/reg pair
type cnt_reg_t is array(1 to 2) of stat_reg_t;
-- each of 6 kinds gets a counter/reg
type cnt_t is array(enumeration_t) of cnt_reg_t;
-- signle reg value
constant stat_reg_clr : stat_reg_t := (stat_reg_t'range => '0');
-- two regs value
constant stat_cnt_clr : cnt_reg_t := (cnt_reg_t'range =>
stat_reg_clr);
-- all regs value
constant cnt_clr : cnt_t := (cnt_t'range => stat_cnt_clr);
-- all regs instance
variable cnt : cnt_t;

Then after the BEGIN I can
use and update these variables
inside the process to infer the whole
truckload of gates and flops.

Are there guidelines for writing synthesisable functions, or is this
vendor specific in the main?
A function is not a synthesizable unit by itself,
but I use them all the time in synthesizable
design entities to update register values.

I haven't written up any synthesis guidelines,
but you can infer some from reference design here:
http://home.comcast.net/~mike_treseler/

Counters, shifters, controllers, rom and ram
can all be inferred from generic vhdl code.
PLL stuff is device specific, and can be
black-boxed using an unbound component instance
in the vhdl source.


-- Mike Treseler
 
Thanks for the help.
I assume the way to select which input is going to be used is to do
something like:
input_g : for j in 0 to numInputs-1 generate
slice_g : for i in 0 to slices-1 generate
slice_p : process(...)
begin
( inputs(j) )( width * (i+1) - 1 downto width*i ) <= lines;

But I'm unsure whether or not that is the correct way to handle
multidimensional arrays in VHDL. I'll have a look at this. Can you
comment on this as an approach please?
 
eddie wrote:
Thanks for the help.
I assume the way to select which input is going to be used is to do
something like:
input_g : for j in 0 to numInputs-1 generate
slice_g : for i in 0 to slices-1 generate
slice_p : process(...)
begin
( inputs(j) )( width * (i+1) - 1 downto width*i ) <= lines;

But I'm unsure whether or not that is the correct way to handle
multidimensional arrays in VHDL. I'll have a look at this. Can you
comment on this as an approach please?
I don't use multidimensional arrays enough to know off the top of my
head. But yes, it should be something like that.
 

Welcome to EDABoard.com

Sponsor

Back
Top