spi.vhd error?


kk_omnisys

Recommended Posts

Hello All

 

I've been working on some external SPI hardware that wants new data on falling edge of SCK and samples at rising edge.

 

I've hooked up my Papilio to a logic analyzer to watch the SPI stream, but to my dismay it seems that the MOSI only clocks out data on rising edge of SCK and the SPI blocks do not listen to the samprise input of spi.vhd

 

I'm just wondering if this is intentionally so or if it is in error?

 

Regards

Kalle

Link to comment
Share on other sites

Hi Jack

 

I'm using the standard spi.vhd from zpu\hdl\zpuino\spi.vhd

 

In particular I believe that the process which shifts the MOSI on lines 107-122 should also depend on samprise and clkfall and not just clkrise.

 

Currently it states the following

  process(ready_q, clkrise)  begin    if ready_q='0' and clkrise='1' then      do_shift<='1';    else      do_shift<='0';    end if;  end process;

I propose that it should say something like

process(ready_q, clkrise, clkfall)begin    if ready_q='0' and samprise = '1' and clkrise='1' then		do_shift <= '1';	elsif ready_q='0' and samprise = '0' and clkfall = '1' then		do_shift <= '1';    else		do_shift<='0';    end if;end process;

But then we end up with something that does not align correctly, the data is shifted on falling edge of SCK, but the first bit is not shifted until the first clock has passed, i.e you try to send 0x80 for example and the logic analyzer takes this as 0x40...

 

Regards

Link to comment
Share on other sites

On second thought I think that it really should say

process(ready_q, clkrise, clkfall)begin    if ready_q='0' and samprise = '0' and clkrise='1' then		do_shift <= '1';	elsif ready_q='0' and samprise = '1' and clkfall = '1' then		do_shift <= '1';    else		do_shift<='0';    end if;end process;

So that data is shifted on the opposite edge of the sampling edge... But I might be wrong..

Link to comment
Share on other sites

I agree that the signals look like they align good enough for the different SPI modes, but:

 

I think that the data should be pushed out so that the MOSI data is already on the data line half a SCK cycle before the leading edge on mode 0,0 because if the data is pushed at the same time as SCK is driven high there will be racing conditions occuring when interfacing with external hardware.. 

 

I have attached the actual waveform captured with my logic analyzer as well as a template of how I thought that mode 0,0 should look

 

Best Regards

Kalle

post-36776-0-42774600-1381831940_thumb.j

post-36776-0-96598700-1381831992_thumb.j

Link to comment
Share on other sites

I think I understood now. Your problem is with CPHA (phase), not with CPOL.

 

So, with CPHA, you want the output to occur "before" the first rising edge.

 

Let me do some quick testing over here, and I'll let you know the best way to ensure all the common PHA/POL alignments. Truth is, most devices do use (1,1) as their preferred standard, so I actually never had to use (0,0).

 

Sorry for not having understood the issue right away.

 

Best,

Alvie

Link to comment
Share on other sites

  • 3 weeks later...

I fixed the spi.vhd (also modded the spiclk.vhd to get an extra clkfall at transfer start to push first bit to stream, changes below) to support both cpha modes, but now i get into trouble with ZAP.

The flash is no longer recognized by ZAP, some help?

 
----  SPI interface-- --  Copyright 2010 Alvaro Lopes <alvieboy@alvie.com>-- --  Version: 1.0-- --  The FreeBSD license--  --  Redistribution and use in source and binary forms, with or without--  modification, are permitted provided that the following conditions--  are met:--  --  1. Redistributions of source code must retain the above copyright--     notice, this list of conditions and the following disclaimer.--  2. Redistributions in binary form must reproduce the above--     copyright notice, this list of conditions and the following--     disclaimer in the documentation and/or other materials--     provided with the distribution.--  --  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY--  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,--  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A--  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE--  ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,--  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES--  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS--  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)--  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,--  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF--  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.--  --library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity spi is  port (    clk			: in  std_logic;    rst			: in  std_logic;    din			: in  std_logic_vector(31 downto 0);    dout		: out std_logic_vector(31 downto 0);    en			: in  std_logic;    ready		: out std_logic;    transfersize: in  std_logic_vector(1 downto 0);    miso		: in  std_logic;    mosi		: out std_logic;    clk_en		: out std_logic;    clkrise		: in  std_logic;    clkfall		: in  std_logic;    samprise 	: in  std_logic -- Sample on rising edge, shift data on falling edge);end entity spi;architecture behave of spi issignal read_reg_q		: std_logic_vector(31 downto 0);signal write_reg_q		: std_logic_vector(31 downto 0);	signal ready_q			: std_logic;signal count			: integer range 0 to 32;--signal count_val_q:   integer range 0 to 32;signal sample_event		: std_logic;signal do_shift			: std_logic;signal ignore_sample_q	: std_logic;begindout <= read_reg_q;process(samprise,clkrise,clkfall)begin	sample_event <= '0';	if (clkfall = '1' and samprise = '0') then		sample_event <= '1';	elsif (clkrise = '1' and samprise='1') then		sample_event <= '1';	end if;end process;process(ready_q, en)begin	ready <= ready_q;end process;process(ready_q, clkrise, clkfall, samprise, en)begin	if ready_q = '0' and samprise = '0' and clkrise = '1'  then		do_shift <= '1';	elsif ready_q = '0' and samprise = '1' and clkfall = '1'  then		do_shift <= '1';	else		do_shift<='0';	end if;end process;process(clk)begin	if rising_edge(clk) then		if do_shift = '1' then			case transfersize is				when "00" =>					MOSI <= write_reg_q(7); -- 8-bit write				when "01" =>					MOSI <= write_reg_q(15); -- 16-bit write				when "10" =>					MOSI <= write_reg_q(23); -- 24-bit write				when "11" =>					MOSI <= write_reg_q(31); -- 32-bit write				when others => NULL;			end case;		end if;	end if;end process;process(ready_q, clkrise, clkfall, count)begin	if ready_q = '1' then		clk_en <= '0';	else		if count/=0 then			clk_en <= '1';		else			if samprise = '0' then				clk_en <= not clkrise;			elsif samprise = '1' then				clk_en <= not clkfall;			end if;		end if;	end if;end process;process(clk)begin	if rising_edge(clk) then		if rst='1' then			ready_q <= '1';			count <= 0;		else			if ready_q = '1' then				if en = '1' then					ready_q <= '0';					write_reg_q <= din(31 downto 0);					ignore_sample_q <= not samprise;										-- Shift the 32-bit register					case transfersize is						when "00" =>							count <= 8;						when "01" =>							count <= 16;						when "10" =>							count <= 24;						when "11" =>							count <= 32;						when others => NULL;					end case;									end if;			else 				if count/=0 then					if do_shift = '1' then						count <= count - 1;					end if;				else					if clkrise = '1' and ready_q = '0' and samprise = '0' then						ready_q <= '1';					elsif clkfall = '1' and ready_q = '0' and samprise = '1' then						ready_q <= '1';					end if;				end if;			end if;			if ready_q = '0' and sample_event = '1' then				ignore_sample_q <= '0';								if ignore_sample_q = '0' then					write_reg_q(31 downto 0) <= write_reg_q(30 downto 0) & '0';					read_reg_q(31 downto 0) <= read_reg_q(30 downto 0) & MISO;				end if;			end if;		end if;	end if;end process;end behave;
----  SPI Clock generator-- --  Copyright 2010 Alvaro Lopes <alvieboy@alvie.com>-- --  Version: 1.0-- --  The FreeBSD license--  --  Redistribution and use in source and binary forms, with or without--  modification, are permitted provided that the following conditions--  are met:--  --  1. Redistributions of source code must retain the above copyright--     notice, this list of conditions and the following disclaimer.--  2. Redistributions in binary form must reproduce the above--     copyright notice, this list of conditions and the following--     disclaimer in the documentation and/or other materials--     provided with the distribution.--  --  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY--  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,--  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A--  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE--  ZPU PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,--  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES--  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS--  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)--  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,--  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)--  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF--  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.--  --library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity spiclkgen is  port (    clk:   in std_logic;    rst:   in std_logic;    en:    in std_logic;    cpol:  in std_logic;    pres:  in std_logic_vector(2 downto 0);    clkrise: out std_logic;    clkfall: out std_logic;    spiclk:  out std_logic  );end entity spiclkgen;architecture behave of spiclkgen issignal running_q: std_logic;signal clkrise_i: std_logic;signal clkfall_i: std_logic;component prescaler is  port (    clk:    in std_logic;    rst:    in std_logic;    prescale:   in std_logic_vector(2 downto 0);    event:  out std_logic                         );end component prescaler;signal prescale_q: std_logic_vector(2 downto 0);signal clk_i: std_logic;signal prescale_event: std_logic;signal prescale_reset: std_logic;signal enq : std_logic;beginclkrise <= clkrise_i;clkfall <= clkfall_i;pr: prescaler  port map (    clk => clk,    rst => prescale_reset,    prescale => prescale_q,    event => prescale_event  );genclk: process(clk)begin  if rising_edge(clk) then    if rst='1' or en='0' then      spiclk <= cpol;    else      if clkrise_i='1' then        spiclk<=not cpol;      end if;      if clkfall_i='1' then        spiclk<=cpol;      end if;    end if;  end if;end process;    process(clk)begin	if rising_edge(clk) then		enq <= en;				if rst='1' then			prescale_q <= (others => '0');			running_q <= '0';			prescale_reset <= '0';		else			if en='1' then				prescale_reset<='0';				running_q <= '1';				if running_q='0' then					prescale_q <= pres;					prescale_reset<='1';				end if;			else				running_q <= '0';			end if;		end if;	end if;end process;process(clk)begin	if rising_edge(clk) then		if rst='1' then			clkrise_i<='0';			clkfall_i<='0';			clk_i<='0';		else			clkrise_i <= '0';			clkfall_i <= '0';						if en = '1' and enq = '0' then				clkfall_i <= '1';			end if;						if running_q='1' and en='1' then				if prescale_event='1' then						clk_i <= not clk_i;					if clk_i='0' then						clkrise_i <= '1';					else						clkfall_i <= '1';					end if;				end if;			else				clk_i <= '0';			end if;		end if;	end if;end process;end behave;

post-36776-0-34778100-1383404949_thumb.j

Link to comment
Share on other sites

  • 3 months later...

Archived

This topic is now archived and is closed to further replies.