W
whygee
Hi,
I have loosely followed the threads on this group and tried to extract some
wisdom from everybody. This is quite useful to me /now/ because I'm
implementing a "simple" SPI master interface for my Actel board.
So I tried to use a single process idea as described by M. Treseler
and his interesting http://mysite.verizon.net/miketreseler/uart.vhd
However my circuit is not a UART. Also I don't much like "state machines"
(I try to avoid them unless really necessary) and I don't see them as
a one-must-fit-all problem solver. And (most importantly)
I need to integrate a clock divider...
I've been busy on this subject for the last 48 hours and I have been
through at least 3 implementations. First I thought about how
the gates would be connected and used to implement the function.
Then I thought "Nah, Mike would beat me if i do that" so I restarted
from scratch, in a "descriptive" and process-driven way.
* As I read the SPI description, like
http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
I see that the sampling on the input is on the opposite edge
of output shifting. This means that I can't use the same register
in the same process and in the same "if (clk'event and clk='1')"
statement. Register reuse (as advocated in the UART document)
is not possible here.
* I had put everything as variables. Then it became obvious
that the ORDER of the assignations is important, while
it is less critical for signals. Well, in a process, you should
care not to write the same signal twice, but it is a blood-thirsty
2-edge sword : it can simplify some statements, but the synthesizer
will maybe not warn when you assign 2x (or more) a value to the
same signal. Or variable.
* Finally, my 2nd thought gave birth to an intricated, monolithic
piece of dense code. It was a sort of huge state machine without the name,
and it would always run at CPU frequency, even though most signals/variables
were updated very infrequently : This was a waste of clock signals,
of energy and routing resources. And I don't think it would have helped
me prevent bugs (despite being seemingly easy to write).
* Oh, and P&R results gave disapointing numbers. It was bloated.
Mostly because the FFs had to support set/reset/enable and this
did not map : a single bit of storage turned into 4 logic elements
(each corresponding to a sort of 3-LUT in Actel technology).
Speed was ok but that did not make me feel more comfortable.
Style depends a lot on the writer and his perception of the design.
For me it's not a problem to write 3 (or even much more) versions of the same thing,
as I'm not "paid for it" (I could be described as a professional hobbyist,
not a full-time engineering mercenary). Experience varies, and various tricks have
different acceptance.
So I decided to split the thing into several parts :
the CPU interface, the programmable clock divider,
the receive shift register and the sender.
Each one can have its own clock so
- power consumption is reduced
- Enable and reset pins can be avoided every time it's possible
(which is very important as I realised that my toolchain does
not accept to have BOTH enable and set/reset despite the
ability of the logic array : This led to a big bloat for the
precedent design).
Working with different clocks is tricky and this is also why
"one big process" can't be the 100% recommended solution
for every design.
Also, splitting up things allows one to test each part
separately (in my case, i check the logic that is generated
and measure the compactness). One can more easily see where
the synthesizer uses the best approach, so it can be guided
to the expected result. When everything is packed together,
it's less easy...
Also, the behavioural/variable/process approach is
not compelling (for me) at least for the final implementation.
I am not concerned by simulation speed gained by the compacity
and the high level of code description. This does not keep
me from using the features of the language (genericity,
modularity, portability etc.)
http://www.designabstraction.co.uk/Articles/Advanced Synthesis Techniques.htm
makes some good points. However I put emphasis on the quality
of the result and I don't care if the source code is bloated
as long as i get what i want in the end. And I am used
to think in the "mousetrap" way for so long that I have
my own methods to ensure that everything works in the end.
I admit however that high-level behavioural description/coding
can be helpful to understand the difficulties and dark corners
(side effects and special cases) of some circuitry.
Also, now, I use variables in a slightly different way :
- variables inside processes to hold temporary results for logic/boolean stuff
- signals when FF is desired.
So it's less prone to unwanted FF inferences and i get a warning when
the order of the variable assignation could cause a trouble.
Finally, I have gotten very nice results :
- the circuit uses 2x less cells than before
- the code uses signals and variables and about 4 processes
- an interesting technique avoids glitches and cross-domain issues
- One saturated Gray counter is used (that could be thought of as a disguised FSM)
However the design is not finished and I'm curious how the
validation will find errors where and why.
A few days will pass before I can draw the first conclusions.
But I really like VHDL because it is very expressive : one has the choice
to use ANY level of description, and (even better) it is possible
to MIX any levels together ! So it is always possible to reach the
desired result in one way or another when a trouble or limitation
appears somewhere. It is also possible to learn this language
progressively, starting with dumb RTL and mastering functions years later.
YG
I have loosely followed the threads on this group and tried to extract some
wisdom from everybody. This is quite useful to me /now/ because I'm
implementing a "simple" SPI master interface for my Actel board.
So I tried to use a single process idea as described by M. Treseler
and his interesting http://mysite.verizon.net/miketreseler/uart.vhd
However my circuit is not a UART. Also I don't much like "state machines"
(I try to avoid them unless really necessary) and I don't see them as
a one-must-fit-all problem solver. And (most importantly)
I need to integrate a clock divider...
I've been busy on this subject for the last 48 hours and I have been
through at least 3 implementations. First I thought about how
the gates would be connected and used to implement the function.
Then I thought "Nah, Mike would beat me if i do that" so I restarted
from scratch, in a "descriptive" and process-driven way.
* As I read the SPI description, like
http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
I see that the sampling on the input is on the opposite edge
of output shifting. This means that I can't use the same register
in the same process and in the same "if (clk'event and clk='1')"
statement. Register reuse (as advocated in the UART document)
is not possible here.
* I had put everything as variables. Then it became obvious
that the ORDER of the assignations is important, while
it is less critical for signals. Well, in a process, you should
care not to write the same signal twice, but it is a blood-thirsty
2-edge sword : it can simplify some statements, but the synthesizer
will maybe not warn when you assign 2x (or more) a value to the
same signal. Or variable.
* Finally, my 2nd thought gave birth to an intricated, monolithic
piece of dense code. It was a sort of huge state machine without the name,
and it would always run at CPU frequency, even though most signals/variables
were updated very infrequently : This was a waste of clock signals,
of energy and routing resources. And I don't think it would have helped
me prevent bugs (despite being seemingly easy to write).
* Oh, and P&R results gave disapointing numbers. It was bloated.
Mostly because the FFs had to support set/reset/enable and this
did not map : a single bit of storage turned into 4 logic elements
(each corresponding to a sort of 3-LUT in Actel technology).
Speed was ok but that did not make me feel more comfortable.
Style depends a lot on the writer and his perception of the design.
For me it's not a problem to write 3 (or even much more) versions of the same thing,
as I'm not "paid for it" (I could be described as a professional hobbyist,
not a full-time engineering mercenary). Experience varies, and various tricks have
different acceptance.
So I decided to split the thing into several parts :
the CPU interface, the programmable clock divider,
the receive shift register and the sender.
Each one can have its own clock so
- power consumption is reduced
- Enable and reset pins can be avoided every time it's possible
(which is very important as I realised that my toolchain does
not accept to have BOTH enable and set/reset despite the
ability of the logic array : This led to a big bloat for the
precedent design).
Working with different clocks is tricky and this is also why
"one big process" can't be the 100% recommended solution
for every design.
Also, splitting up things allows one to test each part
separately (in my case, i check the logic that is generated
and measure the compactness). One can more easily see where
the synthesizer uses the best approach, so it can be guided
to the expected result. When everything is packed together,
it's less easy...
Also, the behavioural/variable/process approach is
not compelling (for me) at least for the final implementation.
I am not concerned by simulation speed gained by the compacity
and the high level of code description. This does not keep
me from using the features of the language (genericity,
modularity, portability etc.)
http://www.designabstraction.co.uk/Articles/Advanced Synthesis Techniques.htm
makes some good points. However I put emphasis on the quality
of the result and I don't care if the source code is bloated
as long as i get what i want in the end. And I am used
to think in the "mousetrap" way for so long that I have
my own methods to ensure that everything works in the end.
I admit however that high-level behavioural description/coding
can be helpful to understand the difficulties and dark corners
(side effects and special cases) of some circuitry.
Also, now, I use variables in a slightly different way :
- variables inside processes to hold temporary results for logic/boolean stuff
- signals when FF is desired.
So it's less prone to unwanted FF inferences and i get a warning when
the order of the variable assignation could cause a trouble.
Finally, I have gotten very nice results :
- the circuit uses 2x less cells than before
- the code uses signals and variables and about 4 processes
- an interesting technique avoids glitches and cross-domain issues
- One saturated Gray counter is used (that could be thought of as a disguised FSM)
However the design is not finished and I'm curious how the
validation will find errors where and why.
A few days will pass before I can draw the first conclusions.
But I really like VHDL because it is very expressive : one has the choice
to use ANY level of description, and (even better) it is possible
to MIX any levels together ! So it is always possible to reach the
desired result in one way or another when a trouble or limitation
appears somewhere. It is also possible to learn this language
progressively, starting with dumb RTL and mastering functions years later.
YG