Line 5... |
Line 5... |
-- # 8 pre-scaled clocks (derived from system clock), 8 dedicated chip-select lines (low-active). #
|
-- # 8 pre-scaled clocks (derived from system clock), 8 dedicated chip-select lines (low-active). #
|
-- # Interrupt: "transfer done" #
|
-- # Interrupt: "transfer done" #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # BSD 3-Clause License #
|
-- # BSD 3-Clause License #
|
-- # #
|
-- # #
|
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
|
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
-- # #
|
-- # #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # permitted provided that the following conditions are met: #
|
-- # permitted provided that the following conditions are met: #
|
-- # #
|
-- # #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
Line 79... |
Line 79... |
constant ctrl_cs3_c : natural := 3; -- r/w: spi CS 3
|
constant ctrl_cs3_c : natural := 3; -- r/w: spi CS 3
|
constant ctrl_cs4_c : natural := 4; -- r/w: spi CS 4
|
constant ctrl_cs4_c : natural := 4; -- r/w: spi CS 4
|
constant ctrl_cs5_c : natural := 5; -- r/w: spi CS 5
|
constant ctrl_cs5_c : natural := 5; -- r/w: spi CS 5
|
constant ctrl_cs6_c : natural := 6; -- r/w: spi CS 6
|
constant ctrl_cs6_c : natural := 6; -- r/w: spi CS 6
|
constant ctrl_cs7_c : natural := 7; -- r/w: spi CS 7
|
constant ctrl_cs7_c : natural := 7; -- r/w: spi CS 7
|
--
|
|
constant ctrl_en_c : natural := 8; -- r/w: spi enable
|
constant ctrl_en_c : natural := 8; -- r/w: spi enable
|
constant ctrl_cpha_c : natural := 9; -- r/w: spi clock phase
|
constant ctrl_cpha_c : natural := 9; -- r/w: spi clock phase
|
constant ctrl_prsc0_c : natural := 10; -- r/w: spi prescaler select bit 0
|
constant ctrl_prsc0_c : natural := 10; -- r/w: spi prescaler select bit 0
|
constant ctrl_prsc1_c : natural := 11; -- r/w: spi prescaler select bit 1
|
constant ctrl_prsc1_c : natural := 11; -- r/w: spi prescaler select bit 1
|
constant ctrl_prsc2_c : natural := 12; -- r/w: spi prescaler select bit 2
|
constant ctrl_prsc2_c : natural := 12; -- r/w: spi prescaler select bit 2
|
constant ctrl_size0_c : natural := 13; -- r/w: data size lsb (00: 8-bit, 01: 16-bit)
|
constant ctrl_size0_c : natural := 13; -- r/w: data size lsb (00: 8-bit, 01: 16-bit)
|
constant ctrl_size1_c : natural := 14; -- r/w: data size msb (10: 24-bit, 11: 32-bit)
|
constant ctrl_size1_c : natural := 14; -- r/w: data size msb (10: 24-bit, 11: 32-bit)
|
constant ctrl_cpol_c : natural := 15; -- r/w: spi clock polarity
|
constant ctrl_cpol_c : natural := 15; -- r/w: spi clock polarity
|
|
constant ctrl_highspeed_c : natural := 16; -- r/w: spi high-speed mode enable (ignoring ctrl_prsc)
|
--
|
--
|
constant ctrl_busy_c : natural := 31; -- r/-: spi transceiver is busy
|
constant ctrl_busy_c : natural := 31; -- r/-: spi transceiver is busy
|
--
|
--
|
signal ctrl : std_ulogic_vector(15 downto 0);
|
signal ctrl : std_ulogic_vector(16 downto 0);
|
|
|
-- access control --
|
-- access control --
|
signal acc_en : std_ulogic; -- module access enable
|
signal acc_en : std_ulogic; -- module access enable
|
signal addr : std_ulogic_vector(31 downto 0); -- access address
|
signal addr : std_ulogic_vector(31 downto 0); -- access address
|
signal wren : std_ulogic; -- word write enable
|
signal wren : std_ulogic; -- word write enable
|
Line 110... |
Line 110... |
busy : std_ulogic;
|
busy : std_ulogic;
|
start : std_ulogic;
|
start : std_ulogic;
|
sreg : std_ulogic_vector(31 downto 0);
|
sreg : std_ulogic_vector(31 downto 0);
|
bitcnt : std_ulogic_vector(05 downto 0);
|
bitcnt : std_ulogic_vector(05 downto 0);
|
bytecnt : std_ulogic_vector(02 downto 0);
|
bytecnt : std_ulogic_vector(02 downto 0);
|
sdi_sync : std_ulogic_vector(01 downto 0);
|
sdi_sync : std_ulogic;
|
end record;
|
end record;
|
signal rtx_engine : rtx_engine_t;
|
signal rtx_engine : rtx_engine_t;
|
|
|
begin
|
begin
|
|
|
Line 143... |
Line 143... |
ctrl(ctrl_cs3_c) <= data_i(ctrl_cs3_c);
|
ctrl(ctrl_cs3_c) <= data_i(ctrl_cs3_c);
|
ctrl(ctrl_cs4_c) <= data_i(ctrl_cs4_c);
|
ctrl(ctrl_cs4_c) <= data_i(ctrl_cs4_c);
|
ctrl(ctrl_cs5_c) <= data_i(ctrl_cs5_c);
|
ctrl(ctrl_cs5_c) <= data_i(ctrl_cs5_c);
|
ctrl(ctrl_cs6_c) <= data_i(ctrl_cs6_c);
|
ctrl(ctrl_cs6_c) <= data_i(ctrl_cs6_c);
|
ctrl(ctrl_cs7_c) <= data_i(ctrl_cs7_c);
|
ctrl(ctrl_cs7_c) <= data_i(ctrl_cs7_c);
|
--
|
|
ctrl(ctrl_en_c) <= data_i(ctrl_en_c);
|
ctrl(ctrl_en_c) <= data_i(ctrl_en_c);
|
ctrl(ctrl_cpha_c) <= data_i(ctrl_cpha_c);
|
ctrl(ctrl_cpha_c) <= data_i(ctrl_cpha_c);
|
ctrl(ctrl_prsc0_c) <= data_i(ctrl_prsc0_c);
|
ctrl(ctrl_prsc0_c) <= data_i(ctrl_prsc0_c);
|
ctrl(ctrl_prsc1_c) <= data_i(ctrl_prsc1_c);
|
ctrl(ctrl_prsc1_c) <= data_i(ctrl_prsc1_c);
|
ctrl(ctrl_prsc2_c) <= data_i(ctrl_prsc2_c);
|
ctrl(ctrl_prsc2_c) <= data_i(ctrl_prsc2_c);
|
ctrl(ctrl_size0_c) <= data_i(ctrl_size0_c);
|
ctrl(ctrl_size0_c) <= data_i(ctrl_size0_c);
|
ctrl(ctrl_size1_c) <= data_i(ctrl_size1_c);
|
ctrl(ctrl_size1_c) <= data_i(ctrl_size1_c);
|
ctrl(ctrl_cpol_c) <= data_i(ctrl_cpol_c);
|
ctrl(ctrl_cpol_c) <= data_i(ctrl_cpol_c);
|
|
ctrl(ctrl_highspeed_c) <= data_i(ctrl_highspeed_c);
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- read access --
|
-- read access --
|
data_o <= (others => '0');
|
data_o <= (others => '0');
|
Line 167... |
Line 167... |
data_o(ctrl_cs3_c) <= ctrl(ctrl_cs3_c);
|
data_o(ctrl_cs3_c) <= ctrl(ctrl_cs3_c);
|
data_o(ctrl_cs4_c) <= ctrl(ctrl_cs4_c);
|
data_o(ctrl_cs4_c) <= ctrl(ctrl_cs4_c);
|
data_o(ctrl_cs5_c) <= ctrl(ctrl_cs5_c);
|
data_o(ctrl_cs5_c) <= ctrl(ctrl_cs5_c);
|
data_o(ctrl_cs6_c) <= ctrl(ctrl_cs6_c);
|
data_o(ctrl_cs6_c) <= ctrl(ctrl_cs6_c);
|
data_o(ctrl_cs7_c) <= ctrl(ctrl_cs7_c);
|
data_o(ctrl_cs7_c) <= ctrl(ctrl_cs7_c);
|
--
|
|
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
|
data_o(ctrl_en_c) <= ctrl(ctrl_en_c);
|
data_o(ctrl_cpha_c) <= ctrl(ctrl_cpha_c);
|
data_o(ctrl_cpha_c) <= ctrl(ctrl_cpha_c);
|
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c);
|
data_o(ctrl_prsc0_c) <= ctrl(ctrl_prsc0_c);
|
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c);
|
data_o(ctrl_prsc1_c) <= ctrl(ctrl_prsc1_c);
|
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c);
|
data_o(ctrl_prsc2_c) <= ctrl(ctrl_prsc2_c);
|
data_o(ctrl_size0_c) <= ctrl(ctrl_size0_c);
|
data_o(ctrl_size0_c) <= ctrl(ctrl_size0_c);
|
data_o(ctrl_size1_c) <= ctrl(ctrl_size1_c);
|
data_o(ctrl_size1_c) <= ctrl(ctrl_size1_c);
|
data_o(ctrl_cpol_c) <= ctrl(ctrl_cpol_c);
|
data_o(ctrl_cpol_c) <= ctrl(ctrl_cpol_c);
|
|
data_o(ctrl_highspeed_c) <= ctrl(ctrl_highspeed_c);
|
--
|
--
|
data_o(ctrl_busy_c) <= rtx_engine.busy;
|
data_o(ctrl_busy_c) <= rtx_engine.busy;
|
else -- data register (spi_rtx_addr_c)
|
else -- data register (spi_rtx_addr_c)
|
data_o <= rtx_engine.sreg;
|
data_o <= rtx_engine.sreg;
|
end if;
|
end if;
|
Line 195... |
Line 195... |
|
|
|
|
-- Clock Selection ------------------------------------------------------------------------
|
-- Clock Selection ------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
clkgen_en_o <= ctrl(ctrl_en_c); -- clock generator enable
|
clkgen_en_o <= ctrl(ctrl_en_c); -- clock generator enable
|
spi_clk_en <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c)))); -- clock select
|
spi_clk_en <= clkgen_i(to_integer(unsigned(ctrl(ctrl_prsc2_c downto ctrl_prsc0_c)))) or ctrl(ctrl_highspeed_c); -- clock select
|
|
|
|
|
-- Transmission Data Size -----------------------------------------------------------------
|
-- Transmission Data Size -----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
data_size: process(ctrl)
|
data_size: process(ctrl)
|
Line 217... |
Line 217... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
spi_rtx_unit: process(clk_i)
|
spi_rtx_unit: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
-- input (sdi) synchronizer --
|
-- input (sdi) synchronizer --
|
rtx_engine.sdi_sync <= rtx_engine.sdi_sync(0) & spi_sdi_i;
|
rtx_engine.sdi_sync <= spi_sdi_i;
|
|
|
-- output (sdo) buffer --
|
|
case ctrl(ctrl_size1_c downto ctrl_size0_c) is
|
|
when "00" => spi_sdo_o <= rtx_engine.sreg(07); -- 8-bit mode
|
|
when "01" => spi_sdo_o <= rtx_engine.sreg(15); -- 16-bit mode
|
|
when "10" => spi_sdo_o <= rtx_engine.sreg(23); -- 24-bit mode
|
|
when others => spi_sdo_o <= rtx_engine.sreg(31); -- 32-bit mode
|
|
end case;
|
|
|
|
-- defaults --
|
-- defaults --
|
spi_sck_o <= ctrl(ctrl_cpol_c);
|
spi_sck_o <= ctrl(ctrl_cpol_c);
|
irq_o <= '0';
|
irq_o <= '0';
|
|
|
Line 261... |
Line 253... |
|
|
when "111" => -- second half of bit transmission
|
when "111" => -- second half of bit transmission
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
spi_sck_o <= ctrl(ctrl_cpha_c) xnor ctrl(ctrl_cpol_c);
|
spi_sck_o <= ctrl(ctrl_cpha_c) xnor ctrl(ctrl_cpol_c);
|
if (spi_clk_en = '1') then
|
if (spi_clk_en = '1') then
|
rtx_engine.sreg <= rtx_engine.sreg(30 downto 0) & rtx_engine.sdi_sync(rtx_engine.sdi_sync'left);
|
rtx_engine.sreg <= rtx_engine.sreg(30 downto 0) & rtx_engine.sdi_sync;
|
if (rtx_engine.bitcnt(5 downto 3) = rtx_engine.bytecnt) then -- all bits transferred?
|
if (rtx_engine.bitcnt(5 downto 3) = rtx_engine.bytecnt) then -- all bits transferred?
|
irq_o <= '1'; -- interrupt!
|
irq_o <= '1'; -- interrupt!
|
rtx_engine.state(1 downto 0) <= "00"; -- transmission done
|
rtx_engine.state(1 downto 0) <= "00"; -- transmission done
|
else
|
else
|
rtx_engine.state(1 downto 0) <= "10";
|
rtx_engine.state(1 downto 0) <= "10";
|
Line 281... |
Line 273... |
end process spi_rtx_unit;
|
end process spi_rtx_unit;
|
|
|
-- busy flag --
|
-- busy flag --
|
rtx_engine.busy <= '0' when (rtx_engine.state(1 downto 0) = "00") else '1';
|
rtx_engine.busy <= '0' when (rtx_engine.state(1 downto 0) = "00") else '1';
|
|
|
|
-- output bit select --
|
|
spi_output: process(ctrl, rtx_engine)
|
|
begin
|
|
case ctrl(ctrl_size1_c downto ctrl_size0_c) is
|
|
when "00" => spi_sdo_o <= rtx_engine.sreg(07); -- 8-bit mode
|
|
when "01" => spi_sdo_o <= rtx_engine.sreg(15); -- 16-bit mode
|
|
when "10" => spi_sdo_o <= rtx_engine.sreg(23); -- 24-bit mode
|
|
when others => spi_sdo_o <= rtx_engine.sreg(31); -- 32-bit mode
|
|
end case;
|
|
end process spi_output;
|
|
|
|
|
end neorv32_spi_rtl;
|
end neorv32_spi_rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|