- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using the Altera SPI Verlog code as a basis for an SPI / SD card interface for a Z80 based computer using a MAX3000A as the CPLD.
When I clock the SPI bus at a low data rate (around 430Khz or lower, as expected for SD card initialisation) it all works fine, however when I try and lower the clock divider to get a higher frequency after initialisation, anything above the 430Khz mark gives me a set bit 7 on the returned SPI data. At first the set high bit is intermittent at lower data rates, but when I clock it at the highest rate (~3.5Mhz) every byte returned has bit 7 set high. I've checked this with the scope, and when I see a value of 0x80 being returned to the processor, the MISO line is clearly low for the whole 8 clock pulses. And what's even weirder is if I invert the MISO line when storing in the shift register, the returned value is 0xFF to the processor and not 0x7F as you would expect if the data was being clocked in correctly from MISO. The only place the shift register is written is during the transceiving phase, so I cant see how it's corrupted, but equally I cant see how it isn't being corrupted given the results I'm getting. I've attached the source code for the SPI module, I hope someone can help me understand what's going on, as currently this makes no sense to me! I would also add the CPU clock and SPI clock are in different domains, so I've made some changes to make read / write only dependant on the RD / WR lines and not the clock as it was before.Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Where did the code come from? Did you write it?
It looks very much like code for a test bench to me and not something intended for synthesis. The code contains a relatively large number of 'always @' statements. Between them the are implying a lot of signals that will be interpreted as clocks, something that'll cause Quartus a lot of trouble when trying to fit it to the small CPLD you're using. The following discusses always blocks and their intended use: verilog: always @ blocks (http://www-inst.eecs.berkeley.edu/~cs150/sp13/resources/always.pdf) I suggest you have a good look through it. I hope it helps. Regards, Alex- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Where did the code come from? Did you write it? It looks very much like code for a test bench to me and not something intended for synthesis. The code contains a relatively large number of 'always @' statements. Between them the are implying a lot of signals that will be interpreted as clocks, something that'll cause Quartus a lot of trouble when trying to fit it to the small CPLD you're using. The following discusses always blocks and their intended use: verilog: always @ blocks (http://www-inst.eecs.berkeley.edu/~cs150/sp13/resources/always.pdf) I suggest you have a good look through it. I hope it helps. Regards, Alex --- Quote End --- This is Altera sample code from here (search for SPI Master) -- http://www.altera.co.uk/support/examples/max/exm-max.html Thanks for the feedback, I think I'll rewrite it myself now I understand better how SPI works. I must admit, it's not how I would have written it, but then I'm new to hardware design, so I usually think its my lack of experience as to why I don't understand the approach.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Where did the code come from? Did you write it? It looks very much like code for a test bench to me and not something intended for synthesis. The code contains a relatively large number of 'always @' statements. Between them the are implying a lot of signals that will be interpreted as clocks, something that'll cause Quartus a lot of trouble when trying to fit it to the small CPLD you're using. The following discusses always blocks and their intended use: verilog: always @ blocks (http://www-inst.eecs.berkeley.edu/~cs150/sp13/resources/always.pdf) I suggest you have a good look through it. I hope it helps. Regards, Alex --- Quote End --- Hi, thanks for the response. I thought I'd already responded to this thread, but I cant see my post. The code is an Altera sample. I've since re-written the code myself and its running much better, except for one thing -- the clock divider. I'm generating my SPI clock from a counter and using a bit index to perform a power of 2 divide for the clock. The clock generation looks like this --
reg rControl;
wire rClkDivide = rControl;
...
always @ (posedge iclkHost)
begin
...
rClockCounter <= rClockCounter + 1;
rSPIClk <= rClockCounter;
...
end
But I find when I use this, I get random errors occurring in the data with missed byte reads. But if I use a fixed clock like this -- always @ (posedge iclkHost)
begin
...
rClockCounter <= rClockCounter + 1;
rSPIClk <= rClockCounter;
...
end
It works perfectly, and that's at a full 7.5Mhz. At any clock divider taken from the control register, I get errors. I'm really not sure why?? Any pointers on this much appreciated, as otherwise my SPI code is working really well. Thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I sorted the clock divider issue out in the end. Increment the counter on the negative edge of the clock and use the value on the positive edge. I guess I was getting some ripple delay in the counter increment.
It now works perfectly. So ultimately it looks like the sample code isn't fit for use, which is a shame... :(
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page