> Would it make sense to build one serial port and try to
> time division multiplex it to the sixteen sets of inputs,
> perhaps keeping all state information in RAM? Is this a
> feasible or reasonable approach?
Thanks Glen, JG, Rick.
I may try this with something a little easier like a PWM
controller.
thanks
Bob Smith
Reply by rickman●February 4, 20092009-02-04
On Feb 4, 1:32=A0am, Bob Smith <use...@linuxtoys.org> wrote:
> Hi,
>
> I would like to use a Spartan 3 100K FPGA to implement 16
> serial ports. =A0The ports will be fairly simple: 1200 to
> 115200 baud, Tx, Rx, and two flow control lines per port.
>
> I already have a working serial port and could make sixteen
> instances of it. =A0This would chew up a lot of the FPGA.
>
> Is there a better way to build sixteen serial ports?
>
> Would it make sense to build one serial port and try to
> time division multiplex it to the sixteen sets of inputs,
> perhaps keeping all state information in RAM? =A0Is this a
> feasible or reasonable approach?
When you say 16 serial ports will chew up a lot of the FPGA, have you
measured the size of a simple UART? If you need a complex UART with
FIFOs and handshake controls, I doubt that you will be able to save
much by somehow combining them. But if you can use a simple UART with
just data in each direction and just a holding register, I suspect
even 16 of these will not be a big design. If it is, you can build a
state machine that uses the LUTs as distributed RAM to emulate 16
registers and end up with a pretty optimized design.
I just think this will be more work than it is worth. A simple UART
should be on the order of 50 LUTs (I'm estimating here) so even x16
that would only be 800 of almost 2000 LUTs... maybe that *is* a lot.
A sized optimized N duplicated UART might be an interesting design.
Rick
Reply by Jonathan Bromley●February 4, 20092009-02-04
On Tue, 3 Feb 2009 11:24:17 -0800 (PST), jleslie48 wrote:
>> I make the message string:
>> constant project_name_stg : string := "123456789a12345";
>>
>> aka, 15 characters, all is well.
>> I make it 16 characters:
>> constant project_name_stg : string := "123456789a123456";
>>
>> my output becomes:
>> 23456789a1234561
>>
>> were the 1 at the end is indeed the first character not the last.
No conceivable way this could be correlated with the fact
that your UART's FIFO buffer is 16 places deep, surely??? :-)
--
Jonathan Bromley, Consultant
DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com
The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Reply by -jg●February 4, 20092009-02-04
On Feb 4, 7:32=A0pm, Bob Smith <use...@linuxtoys.org> wrote:
> Hi,
>
> I would like to use a Spartan 3 100K FPGA to implement 16
> serial ports. =A0The ports will be fairly simple: 1200 to
> 115200 baud, Tx, Rx, and two flow control lines per port.
>
> I already have a working serial port and could make sixteen
> instances of it. =A0This would chew up a lot of the FPGA.
>
> Is there a better way to build sixteen serial ports?
>
> Would it make sense to build one serial port and try to
> time division multiplex it to the sixteen sets of inputs,
> perhaps keeping all state information in RAM? =A0Is this a
> feasible or reasonable approach?
What did your calculator say ?
115200 baud is 8.68us, at x8 or 16 sampling, that's ~2MHz. Split that
16 ways
and you have ~32MHz - does not sound high.....
15-16 byte fifos would likely fit into a ~byte sized state variable.
Reply by glen herrmannsfeldt●February 4, 20092009-02-04
Bob Smith <usenet@linuxtoys.org> wrote:
> I would like to use a Spartan 3 100K FPGA to implement 16
> serial ports. The ports will be fairly simple: 1200 to
> 115200 baud, Tx, Rx, and two flow control lines per port.
> I already have a working serial port and could make sixteen
> instances of it. This would chew up a lot of the FPGA.
> Is there a better way to build sixteen serial ports?
> Would it make sense to build one serial port and try to
> time division multiplex it to the sixteen sets of inputs,
> perhaps keeping all state information in RAM? Is this a
> feasible or reasonable approach?
So only one data bus for all 16? My first thought is,
assuming you have FIFOs on them, would be to multiplex the
FIFOs (write the port and data into the FIFO) for the
receiver, and then when you read it read the data and port.
For the transmitter, that probably doesn't work, but you
could use one RAM and 32 pointer registers. (top and
bottom for each UART.) Can you use the SRL16 for the
shift registers? Otherwise, a UART shouldn't be all
that big.
-- glen
Reply by Bob Smith●February 4, 20092009-02-04
Hi,
I would like to use a Spartan 3 100K FPGA to implement 16
serial ports. The ports will be fairly simple: 1200 to
115200 baud, Tx, Rx, and two flow control lines per port.
I already have a working serial port and could make sixteen
instances of it. This would chew up a lot of the FPGA.
Is there a better way to build sixteen serial ports?
Would it make sense to build one serial port and try to
time division multiplex it to the sixteen sets of inputs,
perhaps keeping all state information in RAM? Is this a
feasible or reasonable approach?
thanks in advance
Bob Smith
Reply by jleslie48●February 3, 20092009-02-03
On Feb 3, 3:08 pm, jleslie48 <j...@jonathanleslie.com> wrote:
> On Feb 3, 2:43 pm, jleslie48 <j...@jonathanleslie.com> wrote:
>
>
>
> > On Feb 3, 2:21 pm, Dave Pollum <vze24...@verizon.net> wrote:
>
> > > On Feb 3, 1:56 pm, jleslie48 <j...@jonathanleslie.com> wrote:
>
> > > > On Feb 3, 1:40 pm, "Thomas J. Gritzan" <phygon_antis...@gmx.de> wro=
> > > > > > ( project_name_cnt ));
> > > > > > ----------------------------------------------------
>
> > > > > > That I see the first character missing problem. I don't know wh=
y the
> > > > > > 'string' version skips the
> > > > > > first character, but the "standard logic vector' version is fin=
e.
>
> > > > > Do you initialize project_name_cnt somewhere?
>
> > > > > --
> > > > > Thomas
>
> > > > good thought but here:
> > > > ----------------------------------------
> > > > -------------------------------------------------------------------=
>
> > > ------------------------------??? ------------------------
> > > One quick thing I noticed in process "P5":
> > > P5: PROCESS ( CLK_16_6MHZ )
> > > BEGIN
> > > IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN
> > > IF ( RESET_COUNT( 3 DOWNTO 0 ) =3D "1111" ) THEN
> > > RESET_COUNT( 3 DOWNTO 0 ) <=3D "1111";
> > > UART_RESET_BUFFER <=3D '0';
> > > ELSE
> > > RESET_COUNT( 3 DOWNTO 0 ) <=3D RESET_COUNT( 3 DOWNTO 0=
)
> > > + 1 ;
> > > UART_RESET_BUFFER <=3D '1';
> > > END IF;
> > > END IF;
> > > END PROCESS P5;
> > > ------------------------------------???------------------------------=
=A2=BC
> > > The 2nd IF says that if RESET_COUNT is all 1's, then set it to all
> > > 1's. I think that you meant to set it to all 0's. BTW, you don't
> > > need "...(3 downto 0)..." because the signal is defined as (3 downto
> > > 0).
> > > so.....
>
> > > BEGIN
> > > IF ( rising_edge( CLK_16_6MHZ ) ) THEN
> > > IF ( RESET_COUNT =3D "1111" ) THEN
> > > RESET_COUNT <=3D (others =3D> '0'); --=
ALL
> > > bits to '0'
> > > UART_RESET_BUFFER <=3D '0';
> > > ELSE
> > > RESET_COUNT <=3D RESET_COUNT + 1 ;
> > > UART_RESET_BUFFER <=3D '1';
> > > END IF;
> > > END IF;
> > > --------------------
> > > HTH
> > > -Dave Pollum
>
> > well certainly:
>
> > ~ IF ( RESET_COUNT( 3 DOWNTO 0 ) =3D "1111" ) THEN
> > ~ RESET_COUNT( 3 DOWNTO 0 ) <=3D "1111";
>
> > makes no sense. and 'something' bad happens when the 16th character
> > is in the buffer, so this is definitely a near hit at least. lets see
> > how
> > reset_count, uart_reset_buffer are used...
>
> Ok this is a fking mess.
>
> what was done here was this, the "program" starts with
> uart_reset_buffer
> and uart_reset_next high, and the p5 process counts for 16 clock
> pulses
> to allow the system to startup. on the 16th pulse (=3D'1111')
> uart_reset_buffer
> goes low, and as a result of the D-FF that is made up on P6,
> uart_reset_next
> waits one clock pulse to go low. So for 1 and only 1 clock pulse,
>
> IF ( ( UART_RESET_BUFFER =3D '0' ) AND
> ( UART_RESET_NEXT =3D '1' ) ) THEN
>
> is true. This is the trigger for the "hello world" message.
>
> Now I imagine there *must* be a better way to do this, and Jonathan B.
> has
> already pointed out that his section of code is, in technical terms,
> higgley-piggley,
> but it is not causing my current flub.
On Feb 3, 2:43 pm, jleslie48 <j...@jonathanleslie.com> wrote:
> On Feb 3, 2:21 pm, Dave Pollum <vze24...@verizon.net> wrote:
>
>
>
> > On Feb 3, 1:56 pm, jleslie48 <j...@jonathanleslie.com> wrote:
>
> > > On Feb 3, 1:40 pm, "Thomas J. Gritzan" <phygon_antis...@gmx.de> wrote=
> > > > > ( project_name_cnt ));
> > > > > ----------------------------------------------------
>
> > > > > That I see the first character missing problem. I don't know why =
the
> > > > > 'string' version skips the
> > > > > first character, but the "standard logic vector' version is fine.
>
> > > > Do you initialize project_name_cnt somewhere?
>
> > > > --
> > > > Thomas
>
> > > good thought but here:
> > > ----------------------------------------
> > > ---------------------------------------------------------------------=
>
> > > P10: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, UART_RESET_NEXT,
> > > lprj_MESS_TRAN, TX_WRITE_BUFFER_STB )
> > > BEGIN
> > > IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN
> > > IF ( ( UART_RESET_BUFFER =3D '0' ) AND
> > > ( UART_RESET_NEXT =3D '1' ) ) THEN
> > > project_name_cnt <=3D 1; --project_name_cnt'low=
;
>
> > > ELSIF ( ( lprj_MESS_TRAN =3D '1' ) AND
> > > ( TX_WRITE_BUFFER_STB =3D '1' ) AND
> > > ( project_name_cnt /=3D
> > > project_name_stg'high ) ) THEN
> > > project_name_cnt <=3D ( project_name_cnt + 1 );
> > > END IF;
> > > END IF;
> > > END PROCESS P10;
>
> > > ------------------------------------------------------
>
> > > here's the entire source code file:
>
> > >http://jleslie48.com/fpga_uartjl_01/11jlmod/ccuart01/source/LOKI_Top.v=
hd
>
> > ------------------------------??? ------------------------
> > One quick thing I noticed in process "P5":
> > P5: PROCESS ( CLK_16_6MHZ )
> > BEGIN
> > IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN
> > IF ( RESET_COUNT( 3 DOWNTO 0 ) =3D "1111" ) THEN
> > RESET_COUNT( 3 DOWNTO 0 ) <=3D "1111";
> > UART_RESET_BUFFER <=3D '0';
> > ELSE
> > RESET_COUNT( 3 DOWNTO 0 ) <=3D RESET_COUNT( 3 DOWNTO 0 )
> > + 1 ;
> > UART_RESET_BUFFER <=3D '1';
> > END IF;
> > END IF;
> > END PROCESS P5;
> > ------------------------------------???------------------------------=
=A2=BC
> > The 2nd IF says that if RESET_COUNT is all 1's, then set it to all
> > 1's. I think that you meant to set it to all 0's. BTW, you don't
> > need "...(3 downto 0)..." because the signal is defined as (3 downto
> > 0).
> > so.....
>
> > BEGIN
> > IF ( rising_edge( CLK_16_6MHZ ) ) THEN
> > IF ( RESET_COUNT =3D "1111" ) THEN
> > RESET_COUNT <=3D (others =3D> '0'); -- A=
LL
> > bits to '0'
> > UART_RESET_BUFFER <=3D '0';
> > ELSE
> > RESET_COUNT <=3D RESET_COUNT + 1 ;
> > UART_RESET_BUFFER <=3D '1';
> > END IF;
> > END IF;
> > --------------------
> > HTH
> > -Dave Pollum
>
> well certainly:
>
> ~ IF ( RESET_COUNT( 3 DOWNTO 0 ) =3D "1111" ) THEN
> ~ RESET_COUNT( 3 DOWNTO 0 ) <=3D "1111";
>
> makes no sense. and 'something' bad happens when the 16th character
> is in the buffer, so this is definitely a near hit at least. lets see
> how
> reset_count, uart_reset_buffer are used...
Ok this is a fking mess.
what was done here was this, the "program" starts with
uart_reset_buffer
and uart_reset_next high, and the p5 process counts for 16 clock
pulses
to allow the system to startup. on the 16th pulse (=3D'1111')
uart_reset_buffer
goes low, and as a result of the D-FF that is made up on P6,
uart_reset_next
waits one clock pulse to go low. So for 1 and only 1 clock pulse,
IF ( ( UART_RESET_BUFFER =3D '0' ) AND
( UART_RESET_NEXT =3D '1' ) ) THEN
is true. This is the trigger for the "hello world" message.
Now I imagine there *must* be a better way to do this, and Jonathan B.
has
already pointed out that his section of code is, in technical terms,
higgley-piggley,
but it is not causing my current flub.
Reply by jleslie48●February 3, 20092009-02-03
On Feb 3, 2:21 pm, Dave Pollum <vze24...@verizon.net> wrote:
> On Feb 3, 1:56 pm, jleslie48 <j...@jonathanleslie.com> wrote:
>
> > On Feb 3, 1:40 pm, "Thomas J. Gritzan" <phygon_antis...@gmx.de> wrote:
>
> > > jleslie48 wrote:
> > > > --------------------------------------------
> > > > function to_slv(c: character) return std_logic_vector is
> > > > begin
> > > > return std_logic_vector(to_unsigned(character'pos(c), 8));
> > > > end;
>
> > > > constant project_name_stg : string :=3D "Testing 1,2,3,";
> > > > SIGNAL project_name_cnt : INTEGER RANGE 1 to
> > > > project_name_stg'high;
> > > > SIGNAL lprj_MESS_TRAN : STD_LOGIC :=3D '0';
>
> > > > IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN
> > > > IF ( UART_RESET_BUFFER =3D '0' ) THEN
> > > > IF ( ( lprj_MESS_TRAN =3D '1' ) AND
> > > > ( TX_BUFFER_FULL =3D '0' ) AND
> > > > ( TX_WRITE_BUFFER_STB =3D '0' ) ) THEN
> > > > --TX_DATA_IN( 7 DOWNTO 0 ) <=3D PROJE=
> > > > ( project_name_cnt ));
> > > > ----------------------------------------------------
>
> > > > That I see the first character missing problem. I don't know why th=
e
> > > > 'string' version skips the
> > > > first character, but the "standard logic vector' version is fine.
>
> > > Do you initialize project_name_cnt somewhere?
>
> > > --
> > > Thomas
>
> > good thought but here:
> > ----------------------------------------
> > -----------------------------------------------------------------------=
>
> > P10: PROCESS ( CLK_16_6MHZ, UART_RESET_BUFFER, UART_RESET_NEXT,
> > lprj_MESS_TRAN, TX_WRITE_BUFFER_STB )
> > BEGIN
> > IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN
> > IF ( ( UART_RESET_BUFFER =3D '0' ) AND
> > ( UART_RESET_NEXT =3D '1' ) ) THEN
> > project_name_cnt <=3D 1; --project_name_cnt'low;
>
> > ELSIF ( ( lprj_MESS_TRAN =3D '1' ) AND
> > ( TX_WRITE_BUFFER_STB =3D '1' ) AND
> > ( project_name_cnt /=3D
> > project_name_stg'high ) ) THEN
> > project_name_cnt <=3D ( project_name_cnt + 1 );
> > END IF;
> > END IF;
> > END PROCESS P10;
>
> > ------------------------------------------------------
>
> > here's the entire source code file:
>
> >http://jleslie48.com/fpga_uartjl_01/11jlmod/ccuart01/source/LOKI_Top.vhd
>
> ------------------------------??? ------------------------
> One quick thing I noticed in process "P5":
> P5: PROCESS ( CLK_16_6MHZ )
> BEGIN
> IF ( CLK_16_6MHZ =3D '1' AND CLK_16_6MHZ'EVENT ) THEN
> IF ( RESET_COUNT( 3 DOWNTO 0 ) =3D "1111" ) THEN
> RESET_COUNT( 3 DOWNTO 0 ) <=3D "1111";
> UART_RESET_BUFFER <=3D '0';
> ELSE
> RESET_COUNT( 3 DOWNTO 0 ) <=3D RESET_COUNT( 3 DOWNTO 0 )
> + 1 ;
> UART_RESET_BUFFER <=3D '1';
> END IF;
> END IF;
> END PROCESS P5;
> ------------------------------------???------------------------------=A2=
=BC
> The 2nd IF says that if RESET_COUNT is all 1's, then set it to all
> 1's. I think that you meant to set it to all 0's. BTW, you don't
> need "...(3 downto 0)..." because the signal is defined as (3 downto
> 0).
> so.....
>
> BEGIN
> IF ( rising_edge( CLK_16_6MHZ ) ) THEN
> IF ( RESET_COUNT =3D "1111" ) THEN
> RESET_COUNT <=3D (others =3D> '0'); -- ALL
> bits to '0'
> UART_RESET_BUFFER <=3D '0';
> ELSE
> RESET_COUNT <=3D RESET_COUNT + 1 ;
> UART_RESET_BUFFER <=3D '1';
> END IF;
> END IF;
> --------------------
> HTH
> -Dave Pollum
well certainly:
~ IF ( RESET_COUNT( 3 DOWNTO 0 ) =3D "1111" ) THEN
~ RESET_COUNT( 3 DOWNTO 0 ) <=3D "1111";
makes no sense. and 'something' bad happens when the 16th character
is in the buffer, so this is definitely a near hit at least. lets see
how
reset_count, uart_reset_buffer are used...
Reply by jleslie48●February 3, 20092009-02-03
On Feb 3, 2:19 pm, jleslie48 <j...@jonathanleslie.com> wrote:
> On Feb 3, 12:41 pm, jleslie48 <j...@jonathanleslie.com> wrote:
>
>
>
> > On Feb 3, 10:52 am, Mike Treseler <mtrese...@gmail.com> wrote:
>
> > > jleslie48 wrote:
> > > >http://jleslie48.com/fpga_uartjl_01/11jlmod/ccuart01/screencap/screen...
>
> > > > I see the "T" getting in, to the datastream, but I haven't found where
> > > > it got clobbered.
>
> > > Is the reset pulse lined up ok?
>
> > Mike,
>
> > Not sure what you mean here,
>
> > and Jonathan,
>
> > Bingo!
>
> > I reduce the startup message to
> > -----------------------------------------------------
> > constant project_name_stg : string := "1";
> > SIGNAL project_name_cnt : INTEGER RANGE 1 to
> > project_name_stg'high;
> > SIGNAL lprj_MESS_TRAN : STD_LOGIC := '0';
> > ------------------------------------------------------------
>
> > just the one character, and it's there. (good it would of taken me
> > hours
> > to figure out the oscilliscope!)
>
> > so that would imply that the stop bit (aka, the dead-reckoning delay)
> > is the issue yes? or is Mike onto the solution? And why does
> > the standard logic vector not suffer from the same issue?
>
> > Inquiring minds want to know...
>
> Ok,
>
> the mystery gets deeper.
>
> I make the message string:
> constant project_name_stg : string := "123456789a12345";
>
> aka, 15 characters, all is well.
> I make it 16 characters:
> constant project_name_stg : string := "123456789a123456";
>
> my output becomes:
> 23456789a1234561
>
> were the 1 at the end is indeed the first character not the last.
and the string:
constant project_name_stg : string := "f23456789a1234567";
yields the output:
23456789a1234567
I imagine 17 or more is destructive to the first character.