Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SPI posotive and negative edge

Status
Not open for further replies.

BartlebyScrivener

Member level 5
Member level 5
Joined
Feb 8, 2012
Messages
90
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Visit site
Activity points
2,081
I am trying to write an SPI module in VHDL.

I have a signal ...

Code:
 signal shiftreg std_logic_vector(7 downto 0)

On the positive edge of my clock I wish to shift the data in the register and to count how many shifts have taken place

once the counter reaches 8, on the next negative edge I wish to populate/read all bits in parallel.

I have this working fine in simulation, but synthesis does not like the assignment of data on both the posotive and negative edge of a clock in the same process.

When I split the process into two separate processes, synthesis does not like me assigning the signal from two different processes.

Is my only alternative to create a new clock at twice the speed of the original so that I can do everything only on the positive edge of the new clock.
 

It's completely legal to have both positive and negative edge sensitive code in a process, as long as the blocks are executed mutual exclusive and don't write to the same signal. But it's clearer to use separate processes. In both cases, a signal can be only written either on one or the other edge.

A SPI design should work well with this unavoidable restrictions of synthesizable HDL code. It's not really clear what you want to achieve and why you intend to write a signal on both edges.

The restriction only applies, if the regular design clock is also used as SPI clock. That's only reasonable for very fast SPI interfaces with clock frequencies above several 10 MHz, or if the design clock is slow, e.g. using a CPLD without PLL feature.
 
  • Like
Reactions: tpetar

    tpetar

    Points: 2
    Helpful Answer Positive Rating
I am trying to write an SPI module in VHDL.

I have a signal ...

Code:
 signal shiftreg std_logic_vector(7 downto 0)

On the positive edge of my clock I wish to shift the data in the register and to count how many shifts have taken place

once the counter reaches 8, on the next negative edge I wish to populate/read all bits in parallel.

I have this working fine in simulation, but synthesis does not like the assignment of data on both the posotive and negative edge of a clock in the same process.

When I split the process into two separate processes, synthesis does not like me assigning the signal from two different processes.

Is my only alternative to create a new clock at twice the speed of the original so that I can do everything only on the positive edge of the new clock.

there is no need to work with both rising_edge and falling_edge for SPI design.
 

there is no need to work with both rising_edge and falling_edge for SPI design.

Am I misunderstanding something then?

As far as I understand it, I have an 8 bit shift register/frame,

data is shifted in and out serially on one edge of the clock,

data is sampled/written in parallel on the other edge once a complete frame has been transmitted?
 

data is shifted in and out serially on one edge of the clock,

data is sampled/written in parallel on the other edge once a complete frame has been transmitted?
Yes, at least at lower SPI speeds. In so far a typical SPI interface acts on both edges of the SPI clock. But the SPI clock isn't necessarily the design clock. And if it is, you don't need to write the same signal on both edges.
 
  • Like
Reactions: tpetar

    tpetar

    Points: 2
    Helpful Answer Positive Rating
Could you explain what you mean by the difference between the design clock and SPI clock and why that would mean I do not need to write the data on both edges?

For my slave device...

I have the signal 'shiftreg(7 downto 0)' to store my 8 bits,
the data to transmit to the master comes from an input 'datatx'
the data recieved serially from the master should be output to 'datarx',

I combinatorial connect 'MISO' to shiftreg(0)

the data should be shifted on, say, the positive edge of the SCLK.

Code:
datatx : in std_logic_vector(7 downto 0);
datarx : out std_logic_vector(7 downto 0);

signal shiftreg : std_logic_vector(7 downto 0);

shift : process (sclk)
begin
   if (sclk'event and sclk = '1') then
      shiftreg(7) <= MOSI;
      shiftreg(6 downto 0) <= shiftreg(7 downto 0);
end process

MISO <= shiftreg(0);

After 8 positive edges, the next falling edge datatx should be put into the shiftreg, and datarx should be read from the shiftreg

Code:
txrx : process (sclk)
begin
   if (sclk'event and sclk = '0') then
      if (shift_count = 8)
      shiftreg(7 downto 0) <= datatx;
      datarx <= shiftreg(7 downto 0);
end process

This new data should be then sent on the next positive edge.

The result should be that data is continually shifted serially into and out of the register on the positive edge of SCLK and is loaded and sampled in parallel every 8th negative edge of SCLK.

But this means I am writing to a signal on two edges of SCLK which the synthesiser does not like. My code works fine in simulation.
 
Last edited:

About the difference between design and SPI clock, I would refer to a different recent discussion https://www.edaboard.com/threads/292625/

The problem shoudn't be viewn primarly from the SPI side. The design clock is driving your overall design. It's selected according to device speed and application requirements. Usually it's somewhere between 30 and 100 MHz. If your SPI interface is considerably slower, you won't generate a slow clock rather than a slow clock enble signal, in this case a clock enable signal of double the SCK frequency. The problem of writing a signal on both edges disappears.

But as said, there are also SPI interfaces that operate at e.g. 50 MHz and use the design clock directly or a specfic clock generated by a PLL. Or the clock is fed externally, as in case of a SPI slave. In so far, the problem in your code example is still relevant.

First comment, the code does not implement the SPI scheme stated in your initial post, because it's sampling MISO and writing MOSI on the same (rising) clock edge.

Presumed you are using the same shift register for RX and TX, MOSI must be delayed related to SR by a half clock cycle. But SR can be still loaded on rising SCK edge with the new data.

In FPGA design, it's probably not optimal to use the same shift register, so the problem can be easily avoided, but it might be necessary in a small PLD.

P.S.: To form a reasonable shift register, you should correct like

Code:
  if (sclk'event and sclk = '1') then
      shiftreg(7) <= MOSI;
      shiftreg(6 downto 0) <= shiftreg(7 downto[COLOR="#FF0000"] 1[/COLOR]);
  end if;

By the way, SPI is mostly using MSB first, left shift rather than right shift.

P.P.S: I assumed a SPI master in my discussion, but I see that it's meaned as SPI slave. So MISO and MOSI are exchanged. Also SCK is usually external. So you either use SCK as external clock for the SPI interface, needing domain crossing synchronization means between the SPI interface and the rest of your design. Or synchronize SCK, MOSI and nCS to your design clock, if SCK is sufficiently slow. But that's partly beyond the original problem, I think.
 
Last edited:
  • Like
Reactions: tpetar

    tpetar

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top