Merge pull request #336 from stnolting/fix_spi_phase_offset

🐛 fix SPI & XIP clock phase offset
This commit is contained in:
stnolting 2022-06-04 11:06:34 +02:00 committed by GitHub
commit 6a412d6ee4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 16 deletions

View file

@ -32,6 +32,7 @@ mimpid = 0x01040312 => 01.04.03.12 => Version 01.04.03.12 => v1.4.3.12
| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 04.06.2022 | 1.7.2.3 | :bug: fixed bug in **SPI** and **XIP** modules: phase offset between SPI clock and SPI data; [#336](https://github.com/stnolting/neorv32/pull/336) |
| 03.06.2022 | 1.7.2.2 | :sparkles: (finally) added a **dedicated hardware reset** to all IO/peripheral devices; [#334](https://github.com/stnolting/neorv32/pull/334) |
| 02.06.2022 | 1.7.2.1 | :sparkles: add **watchdog** pause flag to stop watchdog timeout counter when CPU is in sleep mode; [#331](https://github.com/stnolting/neorv32/pull/331) |
| 02.06.2022 | [**:rocket:1.7.2**](https://github.com/stnolting/neorv32/releases/tag/v1.7.2) | **New release** |

View file

@ -68,7 +68,7 @@ package neorv32_package is
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01070202"; -- NEORV32 version - no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01070203"; -- NEORV32 version - no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
-- Check if we're inside the Matrix -------------------------------------------------------

View file

@ -223,12 +223,8 @@ begin
spi_rtx_unit: process(clk_i)
begin
if rising_edge(clk_i) then
-- input (sdi) synchronizer --
rtx_engine.sdi_sync <= spi_sdi_i;
-- defaults --
spi_sck_o <= ctrl(ctrl_cpol_c);
irq_o <= '0';
irq_o <= '0';
-- serial engine --
rtx_engine.state(2) <= ctrl(ctrl_en_c);
@ -236,6 +232,7 @@ begin
when "100" => -- enabled but idle, waiting for new transmission trigger
-- ------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_cpol_c);
rtx_engine.bitcnt <= (others => '0');
if (rtx_engine.start = '1') then -- trigger new transmission
rtx_engine.sreg <= data_i;
@ -245,32 +242,38 @@ begin
when "101" => -- start with next new clock pulse
-- ------------------------------------------------------------
if (spi_clk_en = '1') then
if (ctrl(ctrl_cpha_c) = '1') then -- clock phase shift
spi_sck_o <= not ctrl(ctrl_cpol_c);
end if;
rtx_engine.state(1 downto 0) <= "10";
end if;
when "110" => -- first half of bit transmission
-- ------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_cpha_c) xor ctrl(ctrl_cpol_c);
if (spi_clk_en = '1') then
spi_sck_o <= not (ctrl(ctrl_cpha_c) xor ctrl(ctrl_cpol_c));
rtx_engine.sdi_sync <= spi_sdi_i; -- sample data input
rtx_engine.bitcnt <= std_ulogic_vector(unsigned(rtx_engine.bitcnt) + 1);
rtx_engine.state(1 downto 0) <= "11";
end if;
when "111" => -- second half of bit transmission
-- ------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_cpha_c) xnor ctrl(ctrl_cpol_c);
if (spi_clk_en = '1') then
rtx_engine.sreg <= rtx_engine.sreg(30 downto 0) & rtx_engine.sdi_sync;
rtx_engine.sreg <= rtx_engine.sreg(30 downto 0) & rtx_engine.sdi_sync; -- shift and set output
if (rtx_engine.bitcnt(5 downto 3) = rtx_engine.bytecnt) then -- all bits transferred?
spi_sck_o <= ctrl(ctrl_cpol_c);
irq_o <= '1'; -- interrupt!
rtx_engine.state(1 downto 0) <= "00"; -- transmission done
else
spi_sck_o <= ctrl(ctrl_cpha_c) xor ctrl(ctrl_cpol_c);
rtx_engine.state(1 downto 0) <= "10";
end if;
end if;
when others => -- "0--": SPI deactivated
-- ------------------------------------------------------------
spi_sck_o <= ctrl(ctrl_cpol_c);
rtx_engine.sreg <= (others => '0');
rtx_engine.state(1 downto 0) <= "00";

View file

@ -488,15 +488,14 @@ begin
ctrl.di_sync <= '-';
else
-- defaults --
spi_clk_o <= cf_cpol_i;
spi_csn_o <= '1'; -- de-selected by default
ctrl.di_sync <= spi_data_i;
spi_csn_o <= '1'; -- de-selected by default
-- fsm --
case ctrl.state is
when S_IDLE => -- wait for new transmission trigger
-- ------------------------------------------------------------
spi_clk_o <= cf_cpol_i;
ctrl.bitcnt <= op_nbytes_i & "000"; -- number of bytes
ctrl.csen <= op_csen_i;
if (op_start_i = '1') then
@ -508,27 +507,32 @@ begin
-- ------------------------------------------------------------
spi_csn_o <= not ctrl.csen;
if (spi_clk_en_i = '1') then
if (cf_cpha_i = '1') then -- clock phase shift
spi_clk_o <= not cf_cpol_i;
end if;
ctrl.state <= S_RTX_A;
end if;
when S_RTX_A => -- first half of bit transmission
-- ------------------------------------------------------------
spi_csn_o <= not ctrl.csen;
spi_clk_o <= cf_cpha_i xor cf_cpol_i;
if (spi_clk_en_i = '1') then
ctrl.bitcnt <= std_ulogic_vector(unsigned(ctrl.bitcnt) - 1);
ctrl.state <= S_RTX_B;
spi_clk_o <= not (cf_cpha_i xor cf_cpol_i);
ctrl.di_sync <= spi_data_i;
ctrl.bitcnt <= std_ulogic_vector(unsigned(ctrl.bitcnt) - 1);
ctrl.state <= S_RTX_B;
end if;
when S_RTX_B => -- second half of bit transmission
-- ------------------------------------------------------------
spi_csn_o <= not ctrl.csen;
spi_clk_o <= not (cf_cpha_i xor cf_cpol_i);
if (spi_clk_en_i = '1') then
ctrl.sreg <= ctrl.sreg(ctrl.sreg'left-1 downto 0) & ctrl.di_sync;
if (or_reduce_f(ctrl.bitcnt) = '0') then -- all bits transferred?
spi_clk_o <= cf_cpol_i;
ctrl.state <= S_DONE; -- transmission done
else
spi_clk_o <= cf_cpha_i xor cf_cpol_i;
ctrl.state <= S_RTX_A; -- next bit
end if;
end if;