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.

Need Help With SPI controller (where CPHA = 1)

Status
Not open for further replies.

BlackHelicopter

Full Member level 2
Joined
Jun 3, 2010
Messages
137
Helped
13
Reputation
26
Reaction score
16
Trophy points
1,298
Activity points
2,207
I'm having trouble with my code when CPHA = '1'. I believe I need to wait a clock pulse before I shift data in the shift register, which I'm not doing. There's probably an easy fix to this but right now I don't see it, can someone show me the right way to do this? (I'm rather new)

I also have a screenshot from a logic analyzer for reference, CPHA = 1 here and the bottom data should be x28 not x14.

Here's the code:

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity SPI_controller is
	generic(num_bits	: positive := 8);
	port(RESET_F     : in std_logic;
		 CSF		 : out std_logic;
		 SYS_CLK	 : in std_logic;
		 CPHA		 : in std_logic;
		 CPOL		 : in std_logic;
		 MOSI		 : out std_logic;
		 MISO		 : in std_logic;
		 rd_data_out : out std_logic_vector(7 downto 0);
		 wr_data_out : out std_logic_vector(7 downto 0);
--		 TEST_POINT  : out std_logic;
		 START_XFR_F : in std_logic;
		 SCLK		 : out std_logic
		 );
end SPI_controller;

architecture arch of SPI_controller is
	type state_type is (IDLE, XMIT, RCV);
	signal state : state_type;
	signal count_max  	   : integer := 20;
	signal count_half      : integer := count_max/2;
	signal clk_count	   : integer := 0;
	signal spi_clk		   : std_logic;
	signal i_spi_clk	   : std_logic;
	signal i_csf		   : std_logic;
	signal start_spi_clk   : std_logic;
--	signal i_test_point    : std_logic;
	signal wr_shift_reg	   : std_logic_vector(7 downto 0);
	signal rd_shift_reg	   : std_logic_vector(7 downto 0);
	signal rd_data_buf	   : std_logic_vector(7 downto 0);
	signal word_size 	   : unsigned(2 downto 0) := "111";
	signal data_count	   : unsigned(2 downto 0);
	signal i_wr_data	   : std_logic_vector(num_bits - 1 downto 0);
	signal spi_start	   : std_logic;
	signal prev_spi_clk    : std_logic;
	signal i_busy		   : std_logic;
	
	
begin

--TEST_POINT <= i_test_point;
SCLK <= i_spi_clk;
CSF <= i_csf;

rd_data_out <= rd_shift_reg;
wr_data_out <= wr_shift_reg;

MOSI <= wr_shift_reg(0);

---==========================================
--  Generate SPI Clk (SCLK Freq)
---==========================================
CLK_DIV : process (SYS_CLK, RESET_F, i_csf)
	begin
		if RESET_F = '0' then
			spi_clk <= '0';
			clk_count <= 0;
		elsif SYS_CLK'event and SYS_CLK = '1' then
			clk_count <= 0;
			spi_clk <= '0';
			if i_csf = '0' then
				if (clk_count < count_max - 1) then
					clk_count <= clk_count + 1;
				else
					clk_count <= 0;
				end if;
				if (clk_count < count_half) then
					spi_clk <= '0';
				else
					spi_clk <= '1';
				end if;
			end if;	
		end if;
	end process;

---==========================================
--  State Machine
---==========================================
STATE_MACHINE : process (SYS_CLK, RESET_F, CPHA)
begin
	if RESET_F = '0' then
		i_csf <= '1';
--		i_test_point <= '0';
		state <= IDLE;
		rd_shift_reg <= (others => '0');
		wr_shift_reg <= x"28";
		data_count <= (others => '0');
		i_busy <= '0';
	elsif SYS_CLK'event and SYS_CLK = '1' then
		prev_spi_clk <= spi_clk;
		if prev_spi_clk = '0' and spi_clk = '1' then
--			i_test_point <= '1'; 
		else
--			i_test_point <= '0';
		end if;
		case state is
			when IDLE =>
				i_csf <= '1';
				if START_XFR_F = '0' and i_busy = '0' then
					i_busy <= '1';
					i_csf <= '0';
					state <= XMIT;
				end if;
			when XMIT =>
				if prev_spi_clk = '1' and spi_clk = '0' then
					if (data_count < word_size) then
						data_count <= data_count + 1;
					else
						data_count <= (others => '0');
						rd_data_buf <= rd_shift_reg;
						state <= IDLE;
					end if;
				end if;
				--  CPHA Handler for SPI Clk
				if CPHA = '0' and prev_spi_clk = '0' and spi_clk = '1' then
					rd_shift_reg <= MISO & rd_shift_reg(7 downto 1);
				elsif CPHA = '0' and prev_spi_clk = '1' and spi_clk = '0' then
					wr_shift_reg <= '0' & wr_shift_reg(7 downto 1);
				elsif CPHA = '1' and prev_spi_clk = '0' and spi_clk = '1' then  -- Need to wait one clock first
					wr_shift_reg <= '0' & wr_shift_reg(7 downto 1);
				elsif CPHA = '1' and prev_spi_clk = '1' and spi_clk = '0' then
					rd_shift_reg <= MISO & rd_shift_reg(7 downto 1);
				end if;
			when RCV =>
				
		end case;
	end if;
end process;

---==========================================
--  CPOL Handler for SPI Clk
---==========================================
OUTPUT_PROC : process (SYS_CLK, RESET_F, CPOL)
begin
	if RESET_F = '0' then
	elsif SYS_CLK'event and SYS_CLK = '1' then
		if CPOL = '1' then
			i_spi_clk <= not spi_clk;
		else
			i_spi_clk <= spi_clk;
		end if;
	end if;
end process;
end arch;
 

Attachments

  • SPI Timing.png
    SPI Timing.png
    6 KB · Views: 56

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top