kk_omnisys Posted October 14, 2013 Report Share Posted October 14, 2013 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? RegardsKalle Link to comment Share on other sites More sharing options...
Jack Gassett Posted October 14, 2013 Report Share Posted October 14, 2013 Hello Kalle, What SPI code are you using? Is it from the ZPUino, the AVR8, or some standalone code? Thanks,Jack. Link to comment Share on other sites More sharing options...
kk_omnisys Posted October 14, 2013 Author Report Share Posted October 14, 2013 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 likeprocess(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 More sharing options...
Jack Gassett Posted October 14, 2013 Report Share Posted October 14, 2013 I think this is a question for Alvie. Let's give him a little time to respond. Jack. Link to comment Share on other sites More sharing options...
kk_omnisys Posted October 14, 2013 Author Report Share Posted October 14, 2013 On second thought I think that it really should sayprocess(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 More sharing options...
alvieboy Posted October 14, 2013 Report Share Posted October 14, 2013 Hello Kalle, If you set SPICPOL=1 and SPISRE=0 you will get the expected behavior: the data will be clocked on the falling edge, and sampled on the rising edge. The VHDL model is correct. The clkrise/fall will be swapped when generating the clock. Link to comment Share on other sites More sharing options...
alvieboy Posted October 14, 2013 Report Share Posted October 14, 2013 Here's a screenshot in simulation, with SPICPOL=1 and SPISRE=0: As you can see, data (MOSI) is clocked out on falling edge, and the sample event is just before the rising edge. Link to comment Share on other sites More sharing options...
kk_omnisys Posted October 15, 2013 Author Report Share Posted October 15, 2013 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 RegardsKalle Link to comment Share on other sites More sharing options...
alvieboy Posted October 15, 2013 Report Share Posted October 15, 2013 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 More sharing options...
alvieboy Posted October 16, 2013 Report Share Posted October 16, 2013 Ok, looks like we are forcing CPHA to '1' on the output. Do you really need to use 0,0 mode ? If so, I will spend a few time "fixing" the issue w/o adding too much complexity to the design. Link to comment Share on other sites More sharing options...
kk_omnisys Posted November 2, 2013 Author Report Share Posted November 2, 2013 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; Link to comment Share on other sites More sharing options...
kk_omnisys Posted February 6, 2014 Author Report Share Posted February 6, 2014 Bump! Should I post this on GITHUB somehow so that it gets merged and so that Alvie or someone can fix the remaining trouble with the ZPUino?? RegardsKalle Link to comment Share on other sites More sharing options...
alvieboy Posted February 6, 2014 Report Share Posted February 6, 2014 Yes, that would be good if you could do a pull request on github. I might need to improve on that so that an extra clockin cycle can be used. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.