Add IPs
This commit is contained in:
104
LAB3/ip/axi4-stream-spi-master/hdl/axis_lw_spi_master.vhd
Normal file
104
LAB3/ip/axi4-stream-spi-master/hdl/axis_lw_spi_master.vhd
Normal file
@@ -0,0 +1,104 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
entity axis_lw_spi_master is
|
||||
generic (
|
||||
c_clkfreq : integer := 100_000_000;
|
||||
c_sclkfreq : integer := 1_000_000;
|
||||
c_cpol : std_logic := '0';
|
||||
c_cpha : std_logic := '0'
|
||||
);
|
||||
Port (
|
||||
aclk : in STD_LOGIC;
|
||||
aresetn : in STD_LOGIC;
|
||||
|
||||
s_axis_tvalid : in STD_LOGIC;
|
||||
s_axis_tdata : in STD_LOGIC_VECTOR(7 downto 0);
|
||||
s_axis_tready : out STD_LOGIC;
|
||||
|
||||
m_axis_tvalid : out STD_LOGIC;
|
||||
m_axis_tdata : out STD_LOGIC_VECTOR(7 downto 0);
|
||||
|
||||
cs : out STD_LOGIC;
|
||||
sclk : out STD_LOGIC;
|
||||
mosi : out STD_LOGIC;
|
||||
miso : in STD_LOGIC
|
||||
);
|
||||
end axis_lw_spi_master;
|
||||
|
||||
architecture Behavioral of axis_lw_spi_master is
|
||||
|
||||
component lw_spi_master is
|
||||
generic (
|
||||
c_clkfreq : integer := 50_000_000;
|
||||
c_sclkfreq : integer := 5_000_000;
|
||||
c_cpol : std_logic := '0';
|
||||
c_cpha : std_logic := '0'
|
||||
);
|
||||
Port (
|
||||
clk_i : in STD_LOGIC;
|
||||
rst_i : in STD_LOGIC;
|
||||
en_i : in STD_LOGIC;
|
||||
mosi_data_i : in STD_LOGIC_VECTOR (7 downto 0);
|
||||
miso_data_o : out STD_LOGIC_VECTOR (7 downto 0);
|
||||
data_ready_o : out STD_LOGIC;
|
||||
cs_o : out STD_LOGIC;
|
||||
sclk_o : out STD_LOGIC;
|
||||
mosi_o : out STD_LOGIC;
|
||||
miso_i : in STD_LOGIC
|
||||
);
|
||||
end component;
|
||||
|
||||
signal rst : std_logic;
|
||||
signal data_ready : std_logic;
|
||||
signal data_ready_reg : std_logic;
|
||||
signal new_data : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
inst_lw_spi_master : lw_spi_master
|
||||
generic map (
|
||||
c_clkfreq => c_clkfreq,
|
||||
c_sclkfreq => c_sclkfreq,
|
||||
c_cpol => c_cpol,
|
||||
c_cpha => c_cpha
|
||||
)
|
||||
Port map (
|
||||
clk_i => aclk,
|
||||
rst_i => rst,
|
||||
en_i => s_axis_tvalid,
|
||||
mosi_data_i => s_axis_tdata,
|
||||
miso_data_o => m_axis_tdata,
|
||||
data_ready_o => data_ready,
|
||||
cs_o => cs,
|
||||
sclk_o => sclk,
|
||||
mosi_o => mosi,
|
||||
miso_i => miso
|
||||
);
|
||||
|
||||
rst <= not aresetn;
|
||||
s_axis_tready <= new_data;
|
||||
m_axis_tvalid <= new_data;
|
||||
|
||||
process (aclk)
|
||||
begin
|
||||
if rising_edge(aclk) then
|
||||
if aresetn = '0' then
|
||||
|
||||
new_data <= '0';
|
||||
|
||||
else
|
||||
|
||||
data_ready_reg <= data_ready;
|
||||
|
||||
if data_ready_reg = '0' and data_ready = '1' then
|
||||
new_data <= '1';
|
||||
else
|
||||
new_data <= '0';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
103
LAB3/ip/axi4-stream-spi-master/hdl/ipi_axis_lw_spi_master.vhd
Normal file
103
LAB3/ip/axi4-stream-spi-master/hdl/ipi_axis_lw_spi_master.vhd
Normal file
@@ -0,0 +1,103 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
entity ipi_axis_lw_spi_master is
|
||||
generic (
|
||||
c_clkfreq : integer := 100_000_000;
|
||||
c_sclkfreq : integer := 1_000_000;
|
||||
c_cpol : integer range 0 to 1 := 0;
|
||||
c_cpha : integer range 0 to 1 := 0
|
||||
);
|
||||
Port (
|
||||
aclk : in STD_LOGIC;
|
||||
aresetn : in STD_LOGIC;
|
||||
|
||||
s_axis_tvalid : in STD_LOGIC;
|
||||
s_axis_tdata : in STD_LOGIC_VECTOR(7 downto 0);
|
||||
s_axis_tready : out STD_LOGIC;
|
||||
|
||||
m_axis_tvalid : out STD_LOGIC;
|
||||
m_axis_tdata : out STD_LOGIC_VECTOR(7 downto 0);
|
||||
|
||||
cs_i : in STD_LOGIC;
|
||||
cs_o : out STD_LOGIC;
|
||||
cs_t : out STD_LOGIC;
|
||||
|
||||
sclk_i : in STD_LOGIC;
|
||||
sclk_o : out STD_LOGIC;
|
||||
sclk_t : out STD_LOGIC;
|
||||
|
||||
mosi_i : in STD_LOGIC;
|
||||
mosi_o : out STD_LOGIC;
|
||||
mosi_t : out STD_LOGIC;
|
||||
|
||||
miso_i : in STD_LOGIC;
|
||||
miso_o : out STD_LOGIC;
|
||||
miso_t : out STD_LOGIC
|
||||
);
|
||||
end ipi_axis_lw_spi_master;
|
||||
|
||||
architecture Behavioral of ipi_axis_lw_spi_master is
|
||||
|
||||
component axis_lw_spi_master is
|
||||
generic (
|
||||
c_clkfreq : integer := 100_000_000;
|
||||
c_sclkfreq : integer := 1_000_000;
|
||||
c_cpol : std_logic := '0';
|
||||
c_cpha : std_logic := '0'
|
||||
);
|
||||
Port (
|
||||
aclk : in STD_LOGIC;
|
||||
aresetn : in STD_LOGIC;
|
||||
|
||||
s_axis_tvalid : in STD_LOGIC;
|
||||
s_axis_tdata : in STD_LOGIC_VECTOR(7 downto 0);
|
||||
s_axis_tready : out STD_LOGIC;
|
||||
|
||||
m_axis_tvalid : out STD_LOGIC;
|
||||
m_axis_tdata : out STD_LOGIC_VECTOR(7 downto 0);
|
||||
|
||||
cs : out STD_LOGIC;
|
||||
sclk : out STD_LOGIC;
|
||||
mosi : out STD_LOGIC;
|
||||
miso : in STD_LOGIC
|
||||
);
|
||||
end component;
|
||||
|
||||
constant C_CPOL_SLV : std_logic_vector := std_logic_vector(to_unsigned(c_cpol, 1));
|
||||
constant C_CPHA_SLV : std_logic_vector := std_logic_vector(to_unsigned(c_cpha, 1));
|
||||
|
||||
begin
|
||||
|
||||
inst_axis_lw_spi_master : axis_lw_spi_master
|
||||
generic map (
|
||||
c_clkfreq => c_clkfreq,
|
||||
c_sclkfreq => c_sclkfreq,
|
||||
c_cpol => C_CPOL_SLV(0),
|
||||
c_cpha => C_CPHA_SLV(0)
|
||||
)
|
||||
Port map (
|
||||
aclk => aclk,
|
||||
aresetn => aresetn,
|
||||
|
||||
s_axis_tvalid => s_axis_tvalid,
|
||||
s_axis_tdata => s_axis_tdata,
|
||||
s_axis_tready => s_axis_tready,
|
||||
|
||||
m_axis_tvalid => m_axis_tvalid,
|
||||
m_axis_tdata => m_axis_tdata,
|
||||
|
||||
cs => cs_o,
|
||||
sclk => sclk_o,
|
||||
mosi => mosi_o,
|
||||
miso => miso_i
|
||||
);
|
||||
|
||||
cs_t <= '0';
|
||||
sclk_t <= '0';
|
||||
mosi_t <= '0';
|
||||
miso_t <= '1';
|
||||
miso_o <= '0';
|
||||
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPI Master Lightweight
|
||||
|
||||
Taken from [OpenCores](https://opencores.org/projects/spi_master_lightweight).
|
||||
Binary file not shown.
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,263 @@
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity lw_spi_master is
|
||||
generic (
|
||||
c_clkfreq : integer := 50_000_000;
|
||||
c_sclkfreq : integer := 5_000_000;
|
||||
c_cpol : std_logic := '0';
|
||||
c_cpha : std_logic := '0'
|
||||
);
|
||||
Port (
|
||||
clk_i : in STD_LOGIC;
|
||||
rst_i : in STD_LOGIC;
|
||||
en_i : in STD_LOGIC;
|
||||
mosi_data_i : in STD_LOGIC_VECTOR (7 downto 0);
|
||||
miso_data_o : out STD_LOGIC_VECTOR (7 downto 0);
|
||||
data_ready_o : out STD_LOGIC;
|
||||
cs_o : out STD_LOGIC;
|
||||
sclk_o : out STD_LOGIC;
|
||||
mosi_o : out STD_LOGIC;
|
||||
miso_i : in STD_LOGIC
|
||||
);
|
||||
end lw_spi_master;
|
||||
|
||||
architecture Behavioral of lw_spi_master is
|
||||
|
||||
signal write_reg : std_logic_vector (7 downto 0) := (others => '0');
|
||||
signal read_reg : std_logic_vector (7 downto 0) := (others => '0');
|
||||
|
||||
signal sclk_en : std_logic := '0';
|
||||
signal sclk : std_logic := '0';
|
||||
signal sclk_prev : std_logic := '0';
|
||||
signal sclk_rise : std_logic := '0';
|
||||
signal sclk_fall : std_logic := '0';
|
||||
|
||||
signal pol_phase : std_logic_vector (1 downto 0) := (others => '0');
|
||||
signal mosi_en : std_logic := '0';
|
||||
signal miso_en : std_logic := '0';
|
||||
|
||||
constant c_edgecntrlimdiv2 : integer := c_clkfreq/(c_sclkfreq*2);
|
||||
signal edgecntr : integer range 0 to c_edgecntrlimdiv2 := 0;
|
||||
|
||||
signal cntr : integer range 0 to 15 := 0;
|
||||
|
||||
type states is (S_IDLE, S_TRANSFER);
|
||||
signal state : states := S_IDLE;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
pol_phase <= c_cpol & c_cpha;
|
||||
|
||||
P_SAMPLE_EN : process (pol_phase, sclk_fall, sclk_rise) begin
|
||||
|
||||
case pol_phase is
|
||||
|
||||
when "00" =>
|
||||
|
||||
mosi_en <= sclk_fall;
|
||||
miso_en <= sclk_rise;
|
||||
|
||||
when "01" =>
|
||||
|
||||
mosi_en <= sclk_rise;
|
||||
miso_en <= sclk_fall;
|
||||
|
||||
when "10" =>
|
||||
|
||||
mosi_en <= sclk_rise;
|
||||
miso_en <= sclk_fall;
|
||||
|
||||
when "11" =>
|
||||
|
||||
mosi_en <= sclk_fall;
|
||||
miso_en <= sclk_rise;
|
||||
|
||||
when others =>
|
||||
|
||||
end case;
|
||||
|
||||
end process;
|
||||
|
||||
P_RISEFALL_DETECT : process (sclk, sclk_prev) begin
|
||||
|
||||
if (sclk = '1' and sclk_prev = '0') then
|
||||
sclk_rise <= '1';
|
||||
else
|
||||
sclk_rise <= '0';
|
||||
end if;
|
||||
|
||||
if (sclk = '0' and sclk_prev = '1') then
|
||||
sclk_fall <= '1';
|
||||
else
|
||||
sclk_fall <= '0';
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
P_MAIN : process (clk_i) begin
|
||||
if (rising_edge(clk_i)) then
|
||||
|
||||
if rst_i = '1' then
|
||||
|
||||
cs_o <= '1';
|
||||
mosi_o <= '0';
|
||||
data_ready_o <= '0';
|
||||
sclk_en <= '0';
|
||||
|
||||
else
|
||||
sclk_prev <= sclk;
|
||||
|
||||
case state is
|
||||
|
||||
when S_IDLE =>
|
||||
|
||||
cs_o <= '1';
|
||||
mosi_o <= '0';
|
||||
data_ready_o <= '0';
|
||||
sclk_en <= '0';
|
||||
cntr <= 0;
|
||||
|
||||
if (c_cpol = '0') then
|
||||
sclk_o <= '0';
|
||||
else
|
||||
sclk_o <= '1';
|
||||
end if;
|
||||
|
||||
if (en_i = '1') then
|
||||
state <= S_TRANSFER;
|
||||
sclk_en <= '1';
|
||||
write_reg <= mosi_data_i;
|
||||
mosi_o <= mosi_data_i(7);
|
||||
read_reg <= x"00";
|
||||
end if;
|
||||
|
||||
when S_TRANSFER =>
|
||||
|
||||
cs_o <= '0';
|
||||
mosi_o <= write_reg(7);
|
||||
|
||||
|
||||
if (c_cpha = '1') then
|
||||
|
||||
if (cntr = 0) then
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
elsif (cntr = 8) then
|
||||
data_ready_o <= '1';
|
||||
miso_data_o <= read_reg;
|
||||
if (mosi_en = '1') then
|
||||
data_ready_o <= '0';
|
||||
if (en_i = '1') then
|
||||
write_reg <= mosi_data_i;
|
||||
mosi_o <= mosi_data_i(7);
|
||||
sclk_o <= sclk;
|
||||
cntr <= 0;
|
||||
else
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
elsif (cntr = 9) then
|
||||
if (miso_en = '1') then
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
else
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
if (mosi_en = '1') then
|
||||
mosi_o <= write_reg(7);
|
||||
write_reg(7 downto 1) <= write_reg(6 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
else -- c_cpha = '0'
|
||||
|
||||
if (cntr = 0) then
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
elsif (cntr = 8) then
|
||||
|
||||
data_ready_o <= '1';
|
||||
miso_data_o <= read_reg;
|
||||
sclk_o <= sclk;
|
||||
if (mosi_en = '1') then
|
||||
data_ready_o <= '0';
|
||||
if (en_i = '1') then
|
||||
write_reg <= mosi_data_i;
|
||||
mosi_o <= mosi_data_i(7);
|
||||
cntr <= 0;
|
||||
else
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
if (miso_en = '1') then
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
elsif (cntr = 9) then
|
||||
if (miso_en = '1') then
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
else
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
if (mosi_en = '1') then
|
||||
write_reg(7 downto 1) <= write_reg(6 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
P_SCLK_GEN : process (clk_i) begin
|
||||
if (rising_edge(clk_i)) then
|
||||
|
||||
if (sclk_en = '1') then
|
||||
if edgecntr = c_edgecntrlimdiv2-1 then
|
||||
sclk <= not sclk;
|
||||
edgecntr <= 0;
|
||||
else
|
||||
edgecntr <= edgecntr + 1;
|
||||
end if;
|
||||
else
|
||||
edgecntr <= 0;
|
||||
if (c_cpol = '0') then
|
||||
sclk <= '0';
|
||||
else
|
||||
sclk <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
@@ -0,0 +1,315 @@
|
||||
--------------------------------------------------------------------------------
|
||||
-- AUTHOR: MEHMET BURAK AYKENAR
|
||||
-- CREATED: 09.12.2019
|
||||
-- REVISION DATE: 09.12.2019
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
-- DESCRIPTION:
|
||||
-- This module implements master part of SPI communication interface and can be used to any SPI slave IC.
|
||||
|
||||
-- In order to read from a slave IC, mosi_data_i input signal should be assigned to desired value and en_i signal should be high.
|
||||
-- In order to write to a slave IC, en_i input signal should be high.
|
||||
-- data_ready_o output signal has the logic high value for one clock cycle as read or/and write operation finished. miso_data_o output signal
|
||||
-- has the data read from slave IC.
|
||||
-- In order to read or/and write consecutively, en_i signal should be kept high. To end the transaction, en_i input signal should be assigned to zero
|
||||
-- when data_ready_o output signal gets high.
|
||||
--------------------------------------------------------------------------------
|
||||
-- Limitation/Assumption: In order to use this module properly, the ratio of (c_clkfreq / c_sclkFreq) should be equal to 8 or more.
|
||||
-- For higher SCLK frequencies are possible but more elaboration is needed.
|
||||
-- Notes: c_cpol and c_cpha parameters are clock polarity and clock phase, respectively.
|
||||
--------------------------------------------------------------------------------
|
||||
-- VHDL DIALECT: VHDL '93
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
-- PROJECT : General purpose
|
||||
-- BOARD : General purpose
|
||||
-- ENTITY : spi_master
|
||||
--------------------------------------------------------------------
|
||||
-- FILE : spi_master.vhd
|
||||
--------------------------------------------------------------------------------
|
||||
-- REVISION HISTORY:
|
||||
-- REVISION DATE AUTHOR COMMENT
|
||||
-- -------- ---------- ------------ -----------
|
||||
-- 1.0 19.12.2019 M.B.AYKENAR INITIAL REVISION
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity spi_master is
|
||||
generic (
|
||||
c_clkfreq : integer := 50_000_000;
|
||||
c_sclkfreq : integer := 1_000_000;
|
||||
c_cpol : std_logic := '0';
|
||||
c_cpha : std_logic := '0'
|
||||
);
|
||||
Port (
|
||||
clk_i : in STD_LOGIC;
|
||||
en_i : in STD_LOGIC;
|
||||
mosi_data_i : in STD_LOGIC_VECTOR (7 downto 0);
|
||||
miso_data_o : out STD_LOGIC_VECTOR (7 downto 0);
|
||||
data_ready_o : out STD_LOGIC;
|
||||
cs_o : out STD_LOGIC;
|
||||
sclk_o : out STD_LOGIC;
|
||||
mosi_o : out STD_LOGIC;
|
||||
miso_i : in STD_LOGIC
|
||||
);
|
||||
end spi_master;
|
||||
|
||||
architecture Behavioral of spi_master is
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- CONSTANTS
|
||||
constant c_edgecntrlimdiv2 : integer := c_clkfreq/(c_sclkfreq*2);
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- INTERNAL SIGNALS
|
||||
signal write_reg : std_logic_vector (7 downto 0) := (others => '0');
|
||||
signal read_reg : std_logic_vector (7 downto 0) := (others => '0');
|
||||
|
||||
signal sclk_en : std_logic := '0';
|
||||
signal sclk : std_logic := '0';
|
||||
signal sclk_prev : std_logic := '0';
|
||||
signal sclk_rise : std_logic := '0';
|
||||
signal sclk_fall : std_logic := '0';
|
||||
|
||||
signal pol_phase : std_logic_vector (1 downto 0) := (others => '0');
|
||||
signal mosi_en : std_logic := '0';
|
||||
signal miso_en : std_logic := '0';
|
||||
signal once : std_logic := '0';
|
||||
|
||||
signal edgecntr : integer range 0 to c_edgecntrlimdiv2 := 0;
|
||||
|
||||
signal cntr : integer range 0 to 15 := 0;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- STATE DEFINITIONS
|
||||
type states is (S_IDLE, S_TRANSFER);
|
||||
signal state : states := S_IDLE;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
begin
|
||||
|
||||
pol_phase <= c_cpol & c_cpha;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- SAMPLE_EN process assigns mosi_en and miso_en internal signals to sclk_fall or sclk_rise in a combinational logic according to
|
||||
-- generic parameters of c_cpol and c_cpha via pol_phase signal.
|
||||
P_SAMPLE_EN : process (pol_phase, sclk_fall, sclk_rise) begin
|
||||
|
||||
case pol_phase is
|
||||
|
||||
when "00" =>
|
||||
|
||||
mosi_en <= sclk_fall;
|
||||
miso_en <= sclk_rise;
|
||||
|
||||
when "01" =>
|
||||
|
||||
mosi_en <= sclk_rise;
|
||||
miso_en <= sclk_fall;
|
||||
|
||||
when "10" =>
|
||||
|
||||
mosi_en <= sclk_rise;
|
||||
miso_en <= sclk_fall;
|
||||
|
||||
when "11" =>
|
||||
|
||||
mosi_en <= sclk_fall;
|
||||
miso_en <= sclk_rise;
|
||||
|
||||
when others =>
|
||||
|
||||
end case;
|
||||
|
||||
end process P_SAMPLE_EN;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- RISEFALL_DETECT process assigns sclk_rise and sclk_fall signals in a combinational logic.
|
||||
P_RISEFALL_DETECT : process (sclk, sclk_prev) begin
|
||||
|
||||
if (sclk = '1' and sclk_prev = '0') then
|
||||
sclk_rise <= '1';
|
||||
else
|
||||
sclk_rise <= '0';
|
||||
end if;
|
||||
|
||||
if (sclk = '0' and sclk_prev = '1') then
|
||||
sclk_fall <= '1';
|
||||
else
|
||||
sclk_fall <= '0';
|
||||
end if;
|
||||
|
||||
end process P_RISEFALL_DETECT;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- In the MAIN process S_IDLE and S_TRANSFER states are implemented. state changes from S_IDLE to S_TRANSFER when en_i input
|
||||
-- signal has the logic high value. At that cycle, write_reg signal is assigned to mosi_data_i input signal. According to c_cpha generic
|
||||
-- parameter, the transaction operation changes slightly. This operational difference is well explained in the paper that can be found
|
||||
-- in Documents folder of the SPI, which is located in SVN server.
|
||||
P_MAIN : process (clk_i) begin
|
||||
if (rising_edge(clk_i)) then
|
||||
|
||||
data_ready_o <= '0';
|
||||
sclk_prev <= sclk;
|
||||
|
||||
case state is
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
when S_IDLE =>
|
||||
|
||||
cs_o <= '1';
|
||||
mosi_o <= '0';
|
||||
data_ready_o <= '0';
|
||||
sclk_en <= '0';
|
||||
cntr <= 0;
|
||||
|
||||
if (c_cpol = '0') then
|
||||
sclk_o <= '0';
|
||||
else
|
||||
sclk_o <= '1';
|
||||
end if;
|
||||
|
||||
if (en_i = '1') then
|
||||
state <= S_TRANSFER;
|
||||
sclk_en <= '1';
|
||||
write_reg <= mosi_data_i;
|
||||
mosi_o <= mosi_data_i(7);
|
||||
read_reg <= x"00";
|
||||
end if;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
when S_TRANSFER =>
|
||||
|
||||
cs_o <= '0';
|
||||
mosi_o <= write_reg(7);
|
||||
|
||||
|
||||
if (c_cpha = '1') then
|
||||
|
||||
if (cntr = 0) then
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
once <= '1';
|
||||
end if;
|
||||
elsif (cntr = 8) then
|
||||
if (once = '1') then
|
||||
data_ready_o <= '1';
|
||||
once <= '0';
|
||||
end if;
|
||||
miso_data_o <= read_reg;
|
||||
if (mosi_en = '1') then
|
||||
if (en_i = '1') then
|
||||
write_reg <= mosi_data_i;
|
||||
mosi_o <= mosi_data_i(7);
|
||||
sclk_o <= sclk;
|
||||
cntr <= 0;
|
||||
else
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
elsif (cntr = 9) then
|
||||
if (miso_en = '1') then
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
else
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
if (mosi_en = '1') then
|
||||
mosi_o <= write_reg(7);
|
||||
write_reg(7 downto 1) <= write_reg(6 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
else -- c_cpha = '0'
|
||||
|
||||
if (cntr = 0) then
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
once <= '1';
|
||||
end if;
|
||||
elsif (cntr = 8) then
|
||||
if (once = '1') then
|
||||
data_ready_o <= '1';
|
||||
once <= '0';
|
||||
end if;
|
||||
miso_data_o <= read_reg;
|
||||
sclk_o <= sclk;
|
||||
if (mosi_en = '1') then
|
||||
if (en_i = '1') then
|
||||
write_reg <= mosi_data_i;
|
||||
mosi_o <= mosi_data_i(7);
|
||||
cntr <= 0;
|
||||
else
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
if (miso_en = '1') then
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
elsif (cntr = 9) then
|
||||
if (miso_en = '1') then
|
||||
state <= S_IDLE;
|
||||
cs_o <= '1';
|
||||
end if;
|
||||
else
|
||||
sclk_o <= sclk;
|
||||
if (miso_en = '1') then
|
||||
read_reg(0) <= miso_i;
|
||||
read_reg(7 downto 1) <= read_reg(6 downto 0);
|
||||
cntr <= cntr + 1;
|
||||
end if;
|
||||
if (mosi_en = '1') then
|
||||
write_reg(7 downto 1) <= write_reg(6 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
end case;
|
||||
|
||||
end if;
|
||||
end process P_MAIN;
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- In the SCLK_GEN process, internal sclk signal is generated if sclk_en signal is '1'.
|
||||
P_SCLK_GEN : process (clk_i) begin
|
||||
if (rising_edge(clk_i)) then
|
||||
|
||||
if (sclk_en = '1') then
|
||||
if edgecntr = c_edgecntrlimdiv2-1 then
|
||||
sclk <= not sclk;
|
||||
edgecntr <= 0;
|
||||
else
|
||||
edgecntr <= edgecntr + 1;
|
||||
end if;
|
||||
else
|
||||
edgecntr <= 0;
|
||||
if (c_cpol = '0') then
|
||||
sclk <= '0';
|
||||
else
|
||||
sclk <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process P_SCLK_GEN;
|
||||
|
||||
end Behavioral;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 186 KiB |
@@ -0,0 +1,233 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.ALL;
|
||||
|
||||
ENTITY tb_lw_spi_master IS
|
||||
END tb_lw_spi_master;
|
||||
|
||||
ARCHITECTURE behavior OF tb_lw_spi_master IS
|
||||
|
||||
-- Component Declaration for the Unit Under Test (UUT)
|
||||
|
||||
COMPONENT lw_spi_master
|
||||
PORT(
|
||||
clk_i : IN std_logic;
|
||||
en_i : IN std_logic;
|
||||
mosi_data_i : IN std_logic_vector(7 downto 0);
|
||||
miso_data_o : OUT std_logic_vector(7 downto 0);
|
||||
data_ready_o : OUT std_logic;
|
||||
cs_o : OUT std_logic;
|
||||
sclk_o : OUT std_logic;
|
||||
mosi_o : OUT std_logic;
|
||||
miso_i : IN std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
|
||||
--Inputs
|
||||
signal clk_i : std_logic := '0';
|
||||
signal en_i : std_logic := '0';
|
||||
signal mosi_data_i : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal miso_i : std_logic := '0';
|
||||
|
||||
--Outputs
|
||||
signal miso_data_o : std_logic_vector(7 downto 0);
|
||||
signal data_ready_o : std_logic;
|
||||
signal cs_o : std_logic;
|
||||
signal sclk_o : std_logic;
|
||||
signal mosi_o : std_logic;
|
||||
|
||||
-- Clock period definitions
|
||||
-- Clock period definitions
|
||||
constant clk_i_period : time := 20 ns;
|
||||
constant sckPeriod : time := 200 ns;
|
||||
|
||||
signal SPISIGNAL : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal spiWrite : std_logic := '0';
|
||||
signal spiWriteDone : std_logic := '0';
|
||||
|
||||
BEGIN
|
||||
|
||||
|
||||
|
||||
-- Instantiate the Unit Under Test (UUT)
|
||||
uut: lw_spi_master PORT MAP (
|
||||
clk_i => clk_i,
|
||||
en_i => en_i,
|
||||
mosi_data_i => mosi_data_i,
|
||||
miso_data_o => miso_data_o,
|
||||
data_ready_o => data_ready_o,
|
||||
cs_o => cs_o,
|
||||
sclk_o => sclk_o,
|
||||
mosi_o => mosi_o,
|
||||
miso_i => miso_i
|
||||
);
|
||||
|
||||
-- Clock process definitions
|
||||
clk_i_process :process
|
||||
begin
|
||||
clk_i <= '0';
|
||||
wait for clk_i_period/2;
|
||||
clk_i <= '1';
|
||||
wait for clk_i_period/2;
|
||||
end process;
|
||||
|
||||
SPIWRITE_P : process begin
|
||||
|
||||
wait until rising_edge(spiWrite);
|
||||
|
||||
-- for cpol = 1 cpha = 1
|
||||
-- for cpol = 0 cpha = 0
|
||||
|
||||
miso_i <= SPISIGNAL(7);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(6);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(5);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(4);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(3);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(2);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(1);
|
||||
wait until falling_edge(sclk_o);
|
||||
miso_i <= SPISIGNAL(0);
|
||||
|
||||
-- for cpol = 0 cpha = 1
|
||||
-- for cpol = 1 cpha = 0
|
||||
|
||||
-- miso_i <= SPISIGNAL(7);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(6);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(5);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(4);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(3);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(2);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(1);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- miso_i <= SPISIGNAL(0);
|
||||
|
||||
spiWriteDone <= '1';
|
||||
wait for 1 ps;
|
||||
spiWriteDone <= '0';
|
||||
|
||||
end process;
|
||||
|
||||
|
||||
-- Stimulus process
|
||||
stim_proc: process
|
||||
begin
|
||||
-- hold reset state for 100 ns.
|
||||
wait for 100 ns;
|
||||
|
||||
wait for clk_i_period*10;
|
||||
|
||||
-- insert stimulus here
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- -- CPOL,CPHA = 00
|
||||
en_i <= '1';
|
||||
|
||||
-- write 0xA7, read 0xB2
|
||||
mosi_data_i <= x"A7";
|
||||
wait until falling_edge(cs_o);
|
||||
SPISIGNAL <= x"B2";
|
||||
spiWrite <= '1';
|
||||
wait until rising_edge(spiWriteDone);
|
||||
spiWrite <= '0';
|
||||
|
||||
-- write 0xB8, read 0xC3
|
||||
wait until rising_edge(data_ready_o);
|
||||
mosi_data_i <= x"B8";
|
||||
wait until falling_edge(data_ready_o);
|
||||
SPISIGNAL <= x"C3";
|
||||
spiWrite <= '1';
|
||||
wait until rising_edge(spiWriteDone);
|
||||
spiWrite <= '0';
|
||||
en_i <= '0';
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- -- CPOL,CPHA = 10
|
||||
-- en_i <= '1';
|
||||
--
|
||||
-- -- write 0xA7, read 0xB2
|
||||
-- mosi_data_i <= x"A7";
|
||||
-- wait until falling_edge(cs_o);
|
||||
-- wait for 50 ns;
|
||||
-- SPISIGNAL <= x"B2";
|
||||
-- spiWrite <= '1';
|
||||
-- wait until rising_edge(spiWriteDone);
|
||||
-- spiWrite <= '0';
|
||||
--
|
||||
-- -- write 0xB8, read 0xC3
|
||||
-- wait until rising_edge(data_ready_o);
|
||||
-- mosi_data_i <= x"B8";
|
||||
-- wait until falling_edge(data_ready_o);
|
||||
-- SPISIGNAL <= x"C3";
|
||||
-- spiWrite <= '1';
|
||||
-- wait until rising_edge(spiWriteDone);
|
||||
-- spiWrite <= '0';
|
||||
-- en_i <= '0';
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- CPOL,CPHA = 01
|
||||
-- en_i <= '1';
|
||||
--
|
||||
-- -- write 0xA7, read 0xB2
|
||||
-- mosi_data_i <= x"A7";
|
||||
-- wait until falling_edge(cs_o);
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- SPISIGNAL <= x"B2";
|
||||
-- spiWrite <= '1';
|
||||
-- wait until rising_edge(spiWriteDone);
|
||||
-- spiWrite <= '0';
|
||||
--
|
||||
-- -- write 0xB8, read 0xC3
|
||||
-- wait until rising_edge(data_ready_o);
|
||||
-- mosi_data_i <= x"B8";
|
||||
-- wait until rising_edge(sclk_o);
|
||||
-- SPISIGNAL <= x"C3";
|
||||
-- spiWrite <= '1';
|
||||
-- wait until rising_edge(spiWriteDone);
|
||||
-- spiWrite <= '0';
|
||||
-- en_i <= '0';
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- -- CPOL,CPHA = 11
|
||||
-- en_i <= '1';
|
||||
--
|
||||
-- -- write 0xA7, read 0xB2
|
||||
-- mosi_data_i <= x"A7";
|
||||
-- wait until falling_edge(cs_o);
|
||||
-- wait until falling_edge(sclk_o);
|
||||
-- SPISIGNAL <= x"B2";
|
||||
-- spiWrite <= '1';
|
||||
-- wait until rising_edge(spiWriteDone);
|
||||
-- spiWrite <= '0';
|
||||
--
|
||||
-- -- write 0xB8, read 0xC3
|
||||
-- wait until rising_edge(data_ready_o);
|
||||
-- mosi_data_i <= x"B8";
|
||||
-- wait until falling_edge(sclk_o);
|
||||
-- SPISIGNAL <= x"C3";
|
||||
-- spiWrite <= '1';
|
||||
-- wait until rising_edge(spiWriteDone);
|
||||
-- spiWrite <= '0';
|
||||
-- en_i <= '0';
|
||||
|
||||
|
||||
|
||||
wait for 1 us;
|
||||
|
||||
assert false
|
||||
report "SIM DONE"
|
||||
severity failure;
|
||||
end process;
|
||||
|
||||
END;
|
||||
Reference in New Issue
Block a user