Re: Mixed clocked/combinatorial coding styles (another thread)
- From: whygee <whygee@xxxxx>
- Date: Mon, 25 Aug 2008 14:06:24 +0200
Hello,
It's a bit scary that, according to my news reader, we posted
to the same newsgroup at the same time with a post that is
roughly the same size, stating with the same extract of a PDF.
As if we had nothing more constructive to do.
What is more scary is some posters' constant desire for
explanations and justifications of *personal choices*.
As if a technical choice was only a technical matter.
We are *all* biased, whether we realize it or not.
Our experiences differ and mature.
And of cource, because this is personal, nobody agrees.
Just like the other thread about coding styles :
there is so much freedom that everybody will
be contented by something that varies according the individuals.
And it's fine for me because I can do more new and great
things every year.
Freedom is wonderful and today's technology is empowering.
We are free to test, experiment, discover, learn and "invent".
So I'm getting a bit tired of "you should do that"
and "that's how it should be done". As if there ware two
kinds of engineers, those who "implement" and those who "innovate"
(often by trial and error).
And I believe that each practical case has distinctive aspects,
that make us reconsider what we know and how we apply our knowledge.
One is free to abide to strict rules, or not. For the rest,
read the standards (and find creative ways to exploit them).
And with YASEP ( http://yasep.org ), I have decided to
go completely wild, unusual and fun (and constructive).
Personally, for the application that has become the focus
of the latest post (SPI master), I have chosen to not be limited
by "what is usually done". I have used a bit of imagination,
confronted the idea to the technical possibilities and
made it work within 48h. The simulations have shown nothing
nasty, and I've learnt some tricks about asynchronous designs
(I wonder why it's so scary for most people, I'm not doing
any FIFO-style magic).
Does somebody need more justifications ?
Shall I quote some nation's constitution ?
I hope not, thank you.
Maybe my error was to think that more Usenet posters would
be open-minded, or at least curious, instead of rehashing
old techniques that I already know work. Now, I realize
that according to some people, pushing the envelope is
not desirable. I did not expect that adding an external
clock input to an otherwise inoffensive circuit would
get the reactions that I have seen. It's just one
stupid pin... Let's all use our 14K8 modems, while
we're at it.
I don't consider my SPI code as finished but I've seen what
I wanted to see, and I'm now looking at the cache memory
system. And once again, it's another occasion to look at
what others have done, what is practically possible, and
how things can be bent, adapted, transformed, twisted,
in order to exploit what is available to perform the
desired functions, and a bit more when the opportunity appears.
24h ago, I thought that it was not even possible to do the
internal cache system.
KJ wrote:
"whygee" <whygee@xxxxx> wrote<snip>Hi !
As pointed in my previous post, there is at least one peripheralIt's always fun when someone refers to mystery stuff like "clocking restrictions (also know as "errata")" instead of simply stating what they are talking about.
(ENC28J60 revB4) that has clocking restrictions
(also know as "errata") and I happen to have some ready-to-use
modules equipped with this otherwise nice chip...
I have "fun" when I imagine something and implement it.
It's more fun when the thing is unusual, like usign a mechanism
to perform another useful function.
I have even more fun when it works as expected.
Oh, and it works. I guess I'm learning and getting better.
Concerning "stating what I was talking about" :
If anybody has to quote every single document about every matter,
then Usenet would become (more) unreadable.
We would need assistants to redact and analyse the posts.
It would be like being a lawyer... and Usenet would
be a courtroom (is it already ?)
So I tried to keep the post short (*sigh*) and
avoided (what I thought) "unecessary details".
There is setup time (Tsu), hold time (Th), clock to ouput (Tco), max frequency (Fmax). That suffices for nearly all timing analysis although sometimes there are others as well such as minimum frequency (Fmin), refresh cycle time, latency time, yadda, yadda, yadda.
Sometimes it's so simple that we don't have to care, sometimes not.
I did a quick search for the erratta *** and came up with...
http://ww1.microchip.com/downloads/en/DeviceDoc/80257d.pdf
bingo.
In there is the following blurb which simply puts a minimum frequency requirement of 8 MHz on your SPI controller design, nothing else.
You see nothing else when I see an opportunity later.
It's a matter of taste, experience, and will of pushing the envelope.
You're not forced to agree with my choices, just as I'm not forced
to follow your advices. I didn't break the entropy principle or
the whole number theory rules. I just added a feature.
I'd go with the work around #1 approach myself since it keeps the ultimate source of the SPI clock at the master where it *should* be for a normal SPI system.
Ok, that's a legitimate point of view.
But does this choice force me to, for example, clock the CPU
with different clocks source, *just* so that the SPI master
interface works in the same clock domain as the CPU ?
Let's see this as an exercise of thinking out of the bag.
-- Start of relevant errata<snip>
-- End of relevant errata
I don't know if my chip revision is B4 and the errata
suggest using a clock between 8 and 10MHz.
However, it also suggest using the ENC28J60-provided 12.5MHz
output :
Read it again. That suggestion was one possible work around, there is nothing there to indicate that this is a preferred solution, just that it is a solution.
This sentence too is hurting.
When facing a choice, where should one go ?
It depends on your objectives, mindset, resources...
So you're basically telling me : don't look, this solution does not exist,
just because there is another one more reassuring (to you) just before.
If I thought like that, I would be some random clerk at some
boring office, not an independent guy earning his life
and his wife's "hacking" things. I would rehash proven things
and let people rule over me.
I'm also concerned by that too.I'm ready to add an external clock input in the master
if i'm allowed to "legally" go beyond the 10MHz rating
(a 25% bandwidth increase is always a good thing, particularly
with real-time communications).
You can run SPI at whatever clock frequeny you choose. What matters is whether you meet the timing requirements of each of the devices on your SPI bus.
I expect some small buffers here and there.
Fortunately, this is much simpler than I2C :-)
In this case, you have a minimum frequency clock requirement of 8 MHZ when communicating with the ENC28J60. If you have other SPI devices on this same bus, this clock frequency does not need to be used when communicating with those devices...of course.
unless of course the ENC28J60 is expecting a free running SPI clock, they don't mention it that way, but I'd be suspicious of it. Many times SPI clock is stopped completely when no comms are ongoing and Figures 4-4 and 4-4 of the data*** seem to imply that the clock is expected to stop for this device as well.
obviously.
As another "unintended case", an external clock input opens
the possibility to bit-bang data with some PC or uC.
I know it sounds stupid :-)
Many times that's the most cost effective approach since the 'cost' is 4 general purpose I/O pins that are usually available. In this case though, maintaining an 8 MHz
hmm this seems to be unfinished, but let me try to continue your phrase :
"maintaining an 8MHz clock on a // port is difficult" (or something like that).
Of course ! that's all the point of having an external clock input !
Though it would be more natural to have a SPI slave instead of a SPI master.
I'll cut into this subject because for the specific purpose of communication
with a host, I intend to use another kind of parallel, synchronous protocol :
4 bits of data, 1 pulse strobe, 1 output enable, 1 reset, 1 "slave data ready".
With some crude software handshake, it's really easy to implement and use,
and 4x faster than SPI.
And there is no "SPI standard" contrary to I2C or others.Yes, all the more freedom you have.
( http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Standards )
So I'd be lazy to not use it.
Note however that your version does not allow to use the CPU clock at full speed, what happens if you set your "max value" to "00000" ?That's correct but I wouldn't set the max value to anything, it would be a computed constant like this
constant Spi_Clks_Per_Cpu_Clk: positive range 2 to positive'high := Spi_Clk_Period / Cpu_Clk_Period.
As I need flexibility (the system I develop is also development platform for me),
the clock divider is programmable. I need to ensure that any combination
of configuration bits won't bork something.
Synthesis (and sim) would fail immediately if the two clock periods were the same since that would result in 'Spi_Clks_Per_Cpu_Clk' coming out to be 1 which is outside of the defined range. Running SPI at the CPU speed is rarely needed since the CPU typically runs much faster than the external SPI bus. If that's not your case, then you've got a wimpy CPU, but in that situation you wouldn't have a clock divider, and the data handling would be done differently. This type of information though is generally known at design time and is not some selectable option so if your CPU did run that slow you wouldn't even bother to write code that would put in a divider so your whole point of "what happens if you set your "max value" to "00000"" is moot.Nice try.
In my case, the SPI divider is programmable, and I expect to be able
to slow down the CPU (from 100 to maybe 20 or 10MHz) when it is not in use
(to conserve power, which is mostly sunk by the main parallel memory interface,
a problem that I am addressing currently).
At the highest frequencies, I assume that it could become a problem.And it does not garantee
that the high and low levels have equal durations.
That's not usually a requirement either.
So since I have a decent frequency margin in the CPU, there's no use
having non-50% duty cycles, when the inherent divide-by-2 (of the code
that I copy-pasted in the previous post) solves the problem before it
appears.
If it is a requirement for some particular application, then one can simply write a function to compute the constant so that it comes out to be an even number. In the case of the ENC28J60 the only specification (Table 16-6) on the SPI clock itself is that it be in the range of DC to 20 MHz, with the errata then ammending that to be 8 MHz min *while* writing to that device. It can still be at DC when not accessing the device. In any case, there is no specific 'SPI clock high time' or 'SPI clock low time' requirement for the device, so unless there is some other errata there is no requirement for this device to have a 50% duty cycle clock.
As pointed in another post about SPI edge sampling,
I was a bit worried that longer-than-expected wiring would cause trouble.
At 20MHz (the latest chips are that fast), I'm not willing to play with the duty cycles.
Sampling clock, maybe, but that would remain experimental.
Fortunately, my scope is fast enough for this case so in practice,
I would find the solution if a problem arises.
Every flop in the design then is synchronously clocked by the Cpu_Clock, there are no other clock domains therefore no clock domain crossings. The counter is used as a divider to signal internally for when things have reached a particular state.I understand that well, as this is how i started my first design iteration
I soon reached some inherent limitations, however.
I doubt those limitations were because of device requirements though...they seem to be your own limitations. If not, then specify what those limitations are. Just like with your previously mentioned "clocking restrictions (also know as "errata")" comment I doubt that these limitations are due to anything in the device requirements.
I don't want to bloat this post (that probably nobody reads) so i'll
cut this useless issue too. Your doubts may be legitimate but they
are not my concern (which is now : cache memory).
Maybe I'll write a full report later, when things have settled and
become clear, in another thread.
I tried to keep the thing as bare as possible, of course.As the RTL code grows, the synthesizer infers more and more stuffs,
often not foreseen, which leads to bloat. Muxes everywhere,
and duplicated logic cells that are necessary to drive higher fanouts.
I guess that this is because I focused more on the "expression"
of my need than on the actual result (but I was careful anyway).
Don't write bloated code.
Use the feedback you're seeing from running your code through synthesis to sharpen your skills on how to write good synthesizable code...there is no substitute for actual experience in gaining knowledge.
Sure. I did that for the precedent project.
But in the end, it backfired as I did not think to try simulation.
I've learnt the lesson.
I have also tried to
maybe I should have been more explicit.No there isn't.No need for the master to resynchronize something that it generates itself (see my other post).In fact, there IS a need to resynchronise the clock, even when
it is generated by the CPU, because of the divider.
I meant : resynchronise the output clock after the divider.
my fault.
<snip>
If I pointed to this case, then I also addressed it in the code.Imagine (I'm picky here) that the CPU runs at 100MHz (my target)
and the slave at 100KHz (an imaginary old chip).
The data transfer is setup in the control register, then
the write to the data register triggers the transfer.
But this can happen at any time, whatever the value of the predivider's counter.
So the clock output may be toggled the first time well below
the required setup time of the slave. That's a glitch.
So don't write such bad code for a design.
There is no need for the clock divider to be running when you're not transmitting.your initial code did not mention this.
It should sit at 0 until the CPU write comes along, then it would step through a 1000+ CPU clock cycle state machine, with the first few clocks used for setting up timing of data relative to chip select and the start of SPI clock.May I address another issue ?
alright, thanks.
CS should be controlled by software, at least with the slaves i intend to use.
Because only the master know how much bytes or half-word it wants.
Most slaves see the CS falling edge as the beginning of the transaction,
and rising edge as the end. Between those two edges, as many words as
desired can be transmitted. For the case of the ENC28J60 or the SPI EEPROM,
one can dump the whole memory in one go if needed.
Emitting a new command word for every new byte is pure overhead and loss.
Then there are a few CPU clocks on the back end for shutting off the chip select and then of course the 1000 CPU clocks needed in order to generate the 100 kHz SPI clock itself. Any time the counter is greater than 0, the SPI controller must be telling the CPU interface to 'wait' while it completes
In the system I build, the CPU MUST poll a "RDY" flag in the control register
before starting a new command, that's the simple software protocol I defined.
If the CPU starts a new transaction when RDY is cleared, then this is a voluntary error,
not the interface's fault. The interface FSM will be reset and restarted
automatically, and the aborted transaction will be lost, that's all.
And this is defined as an error, that I expect will never happen in well
formed SW.
You should make sure your design works in the above scenario as a test case.
The first simulations are encouraging,
but the use of Modelsim is a bit tedious.
I'm learning.
I don't guard with HS because this is the SW's responsibility in this case.In this case, the solution is easy : reset the counterYou haven't guarded against the CPU coming in and attempting to start a second write while the first one is ongoing.
whenever a transfer is requested. That's what i did too,
the first time.
but there is an even simpler solution : add a "clear" input condition
to the FF that are used to resynchronise the clocks as in
http://i.cmpnet.com/eedesign/2003/jun/mahmud3.jpg
so the next clock cycle will be well-formed, whether the
source is internal or external. The created delay is not an issue.
You need a handshake on the CPU side to insert wait states while the controller is spitting out the bits.Ouch, you're tough, here !
In YASEP, there is a dedicated "Special Registers" area dedicated
to general HW configuration and peripherals like the SPI master.
It is mapped as 2 registers : 0 is control/state, 1 is data.
To poll the RDY bit takes 2 instructions and 6 bytes :
label_poll
GET SPI_CTL, R0
JO label_poll ; RDY is in bit 0, which makes R0 Odd when not ready.
When you look at it in that perspective and design it correctly, there will be no chance of any glitchy clocks or anything else. If you don't have a 'wait' signal back to the CPU, then certainly you have an interrupt that you can use to send back to the CPU to indicate that it fouled up by writing too quickly...many possible solutions.
It feels like i'm reading one of those old books I read when aged 14
about how to design a 6809-based system. Thank you Technology for the FPGA !
<snip>
This is what I did in the first design iteration.
However, now, i avoid large single-clock processes
because there is less control over what the synthesiser does.
That makes no sense.
To you, it seems.
Breaking the thing into well defined sub-blocks
communicating with signals has not only made synthesis more predictable (IMHO, YMMV but IANAL)
but also simulation easier (I can't see how to enable visualisation
of variables with Modelsim). So to me, it does make some sense.
To quote another thread, I don't remember who said something like :
"I take the D in VHDL very seriously". While others concentrate on the 'L',
I "think" graphically with diagrams, blocks and signal arrows...
just like with paper. Even after I tried other ways,
I feel more comfortable this way and it gets the job done.
What more do I need ?
I have a certain way of doing things, like anybody else.
I won't tell them that they make no sense.
I'll just sit there and learn, and when I face a design challenge,
I'll weight the pros & cons of the solutions I already know,
and maybe even find a totally different solution.
Your proposed solution wouldn't solve anything. If you have a highly loaded MISO this means you have a lot of loads (or the master and slave are faaaaaaaar apart on separate boards). It also likely means you have a highly loaded SPI clock since each slave device needs a clock. You likely won't be able to find a driver capable of switching the SPI clock so that it is monotonic at each of the loads (which is a requirement)If the case appears, I have some 100s of 74-1G125 single-gate tristate buffers,
this could help. Or i can simply add other dedicated pins to the FPGA (1/slave).
Currently, I'll have 2 fast slaves and maybe one slow remote sensor that could
stand some signal margin (probably < 1MHz).
By the way, I have not been able to find the SPI Switching parameters
of ST's LIS3LV02DQ 3D accelerometer but the transmission speed of this sensor
is not critical, i'll try 100KHz if I can.
Far easier to simply sample MISO a tick or two later. For example, using the 100 MHz/100kHz example you mentioned, the half way point would be 500, but there is nothing to say that you can't sample it at 501, 502 or whatever, it doesn't matter.
This more or less confirms what I was thinking.
It may be useful one day (as well as a good scope).
And now, let's see how I can create some cache memory
with just 3 512-byte reconfigurable memory blocks.
Kevin JenningsYG
.
- Follow-Ups:
- References:
- Mixed clocked/combinatorial coding styles (another thread)
- From: whygee
- Re: Mixed clocked/combinatorial coding styles (another thread)
- From: whygee
- Re: Mixed clocked/combinatorial coding styles (another thread)
- From: whygee
- Re: Mixed clocked/combinatorial coding styles (another thread)
- From: KJ
- Re: Mixed clocked/combinatorial coding styles (another thread)
- From: whygee
- Re: Mixed clocked/combinatorial coding styles (another thread)
- From: KJ
- Mixed clocked/combinatorial coding styles (another thread)
- Prev by Date: Re: bit stuffing
- Next by Date: Re: Mixed clocked/combinatorial coding styles (another thread)
- Previous by thread: Re: Mixed clocked/combinatorial coding styles (another thread)
- Next by thread: Re: Mixed clocked/combinatorial coding styles (another thread)
- Index(es):