Commit 470753fc authored by gilsoriano's avatar gilsoriano

spi master update:

- Added documentation in pdf about register and memory map.
- Added testbench of the spi_master_core.
parent 1182da16
%%This is a very basic article template.
%%There is just one section and two subsections.
\documentclass[a4paper,11pt]{article}
\usepackage[pdfborder= 0 0 0 1]{hyperref}
\usepackage{graphicx}
%%\usepackage{draftwatermark}
%%\SetWatermarkLightness{0.9}
%%\SetWatermarkScale{5}
\begin{document}
\title{SPI multifield HDL core}
\author{Carlos Gil Soriano\\BE-CO-HT\\
\href{mailto:carlos.gil.soriano@cern.ch}{\textbf{\textit{carlos.gil.soriano@cern.ch}}}}
\date{July 20, 2012}
\maketitle
\begin{abstract}
A configurable SPI multifield HDL core is shown. This core is able to
specify three kind of fields to be sent according to SPI communication and
been able to configure independently the lenght of every field.\\
The core is targeted for complexer uses of SPI communications, like writing
blocks of EEPROM memories which typically requiere three fields.\\
The following subjects are addressed:
\begin{itemize}
\item The registers to control the module.
\item Step-by-step instructions for proper use.
access.
\end{itemize}
\end{abstract}
\vspace{2cm}
\begin{center}
\begin{tabular}{|p{2.5cm}|p{3.5cm}|p{3cm}|}
\hline
\multicolumn{3}{|c|}{\textbf{Revision history}}\\
\hline
\hline
\textbf{HDL version} & \textbf{Module} & \textbf{Date}\\
\hline
0.1 & SPI master multifield & July 20, 2012\\
\hline
\end{tabular}
\end{center}
\pagebreak
\tableofcontents
\pagebreak
\section{Structure}
The SPI module contains several blocks related the following way:\\
-- spi\_master\_top.vhd
----- spi\_master\_regs.vhd
----- spi\_master\_slave\_core.vhd
--------- FIFO\_dispatcher.vhd
--------- gc\_counter.vhd
--------- gc\_clk\_divider.vhd\\
The top module combines two components:
\textit{spi\_master\_core} and \textit{spi\_master\_regs}.
The first one can be used independently from thei the top module, saving some
interconnection lines and allowing a direct way of using the module. If access
to the control registers \textit{SPI[X]} through classic Wishbone interface is
desired, then the top module must be used.\\
Due to the target use of this SPI core (block transfers for memory interfaces) all
the three input fields are offered in both the top and the core modules.
Internally, the data in every of the three set of fields is registered by the
control registers, either by directly writing into the \textit{SPI[X]} register
(in the case of \textit{spi\_master\_core}) or through wishbone
(\textit{spi\_master\_top}).
\subsection{Dependencies}
Three components used in this core belongs to general use in CTDAH board.
Due to that they are packed inside \textbf{ctdah\_lib}. The required components
to be imported are:\\
-- FIFO\_dispatcher.vhd
-- gc\_counter.vhd
-- gc\_clk\_divider.vhd
\section{Registers}
\subsection{SPI0}
The SPI0 is a write-read register.\\
\begin{tabular}{| l | c | c | c |}
\hline
\textbf{Bits} & \textbf{Field} & \textbf{Meaning} & \textbf{Default}\\
\hline
\hline
4-0 & x & Reserved & \textbf{"00000"} \\
\hline
13-5 & \textbf{BDATA} & Bytes of DATA to be sent & \textbf{c\_INST\_LENGTH}\\
\hline
22-14 & \textbf{BADDR} & Bytes of ADDRess to be sent & \textbf{c\_ADDR\_LENGTH}\\
\hline
31-23 & \textbf{BINST} & Bytes of INSTruction to be sent& \textbf{c\_DATA\_LENGTH}\\
\hline
\end{tabular}
\subsection{SPI1}
The SPI1 is a write-read register.\\
\begin{tabular}{| l | c | c | c |}
\hline
\textbf{Bits} & \textbf{Field} & \textbf{Meaning} & \textbf{Default}\\
\hline
\hline
0 & \textbf{PUSH\_DATA} & PUSH DATA bytes into & \textbf{'0'} \\
& & internal SPI core memory & \\
\hline
1 & \textbf{PUSH\_ADDR} & PUSH ADDRess bytes into & \textbf{'0'} \\
& & internal SPI core memory & \\
\hline
2 & \textbf{PUSH\_INST} & PUSH INSTruction bytes into& \textbf{'0'} \\
& & internal SPI core memory & \\
\hline
5-3 & x & Reserved & \textbf{"000"} \\
\hline
6 & \textbf{SEND\_DATA} & DATA bytes will be sent in & \textbf{'0'} \\
& & a write operation & \\
\hline
7 & \textbf{SEND\_ADDR} & ADDR bytes will be sent in & \textbf{'0'} \\
& & a write operation & \\
\hline
8 & \textbf{SEND\_INST} & INST bytes will be sent in & \textbf{'0'} \\
& & a write operation & \\
\hline
9 & \textbf{SEND\_OP} & perform a SEND OPeration & \textbf{'0'} \\
\hline
11-10 & y & Reserved & \textbf{"00"} \\
\hline
15-12 & \textbf{CLK\_DIV} & CLocK DIVider & \textbf{X"0"} \\
\hline
31-16 & z & Reserved & \textbf{X"0000"}\\
\hline
\end{tabular}
\subsection{SPI2}
The SPI2 register is a read-only register.\\
\begin{tabular}{| l | c | c | c |}
\hline
\textbf{Bits} & \textbf{Field} & \textbf{Meaning} & \textbf{Default}\\
\hline
\hline
0 & \textbf{SENT\_DATA} & DATA was SENT & \textbf{'0'} \\
\hline
1 & \textbf{SENT\_ADDR} & ADDRess was SENT & \textbf{'0'} \\
\hline
2 & \textbf{SENT\_INST} & INSTruction was SENT & \textbf{'0'} \\
\hline
3 & \textbf{SENT\_OP } & OPeration was SENT & \textbf{'0'} \\
\hline
11-4 & x & Reserved & \textbf{X"00"} \\
\hline
15-12 & \textbf{CLK\_DIV} & CLocK DIVision & \textbf{X"0"} \\
\hline
\end{tabular}
\section{Internal memory mapping}
The internal registers map is as follow:\\
\begin{tabular}{| c | c | c |}
\hline
\textbf{Address} & \textbf{Register} & \textbf{Access} \\
\hline
\hline
\textbf{0x0} & \textit{SPI0} & Write-read \\
\hline
\textbf{0x1} & \textit{SPI1} & Write-read \\
\hline
\textbf{0x2} & \textit{SPI2} & Read-only \\
\hline
\end{tabular}
\section{How to use it}
\subsection{Outputting a stream of data through SPI}
\begin{enumerate}
\item Specify the divider it will be used to construct the SPI clk signal out
of the general clk signal.
\item Place the values to be sent in \textit{inst\_i}, \textit{addr\_i} and
\textit{data\_i}.
\item Register their values by one-clock asserting \textit{PUSH\_[X]} bits in
\textit{SPI1} register.
\item Specify which fields must be sent by asserting \textit{SEND\_[X]} bits in
\textit{SPI1} register. This bits must keep asserted during the whole
send operation.
\item Specify the length in bytes of every field by writing \textit{SPI0}.
\item Assert \textit{SEND\_OP} bit field in \textit{SPI1} register. It must be
keep asserted until \textit{SENT\_OP} is received.
\end{enumerate}
\end{document}
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
--
-- Copyright CERN 2011.
--
-- This documentation describes Open Hardware and is licensed under the
-- CERN OHL v. 1.1.
--
-- You may redistribute and modify this documentation under the terms of the CERN
-- OHL v.1.1. (http://ohwr.org/cernohl).
--
-- This documentation is distributed WITHOUT
-- ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY
-- QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL v.1.1 for
-- applicable conditions.
--
----------------------------------------------------------------------------------
--
-- Company: CERN, BE-CO-HT -- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano -- Engineer: Carlos Gil Soriano
-- --
...@@ -8,13 +24,15 @@ ...@@ -8,13 +24,15 @@
-- Project Name: CTDAH/SVEC -- Project Name: CTDAH/SVEC
-- Target Devices: Spartan 6 -- Target Devices: Spartan 6
-- Tool versions: Xilinx ISE 13.4 -- Tool versions: Xilinx ISE 13.4
-- Description: This is a spi_master with programable field length and progra -- Description: This is a spi_master with programmable field length and progra
-- mable setup and hold chip select times. -- mmable setup and hold chip select times.
-- --
-- Dependencies: -- Dependencies:
-- --
-- Revision: -- Revision: 0.1
-- Revision 0.01 - File Created -- 0.01 + File Created
-- 0.1 - Alpha version. Able to write and output data correctly at
-- different configurations.
-- Additional Comments: -- Additional Comments:
-- --
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
...@@ -33,21 +51,21 @@ entity spi_master_core is ...@@ -33,21 +51,21 @@ entity spi_master_core is
g_DATA_LENGTH : NATURAL := 256; g_DATA_LENGTH : NATURAL := 256;
g_CLK_I_PERIOD : NATURAL := c_CLK_I_PERIOD); g_CLK_I_PERIOD : NATURAL := c_CLK_I_PERIOD);
port( port(
rst_i : in STD_LOGIC; rst_i : in STD_LOGIC;
clk_i : in STD_LOGIC; clk_i : in STD_LOGIC;
inst_i : in STD_LOGIC_VECTOR (8*g_INST_LENGTH - 1 downto 0); inst_i : in STD_LOGIC_VECTOR (8*g_INST_LENGTH - 1 downto 0);
addr_i : in STD_LOGIC_VECTOR (8*g_ADDR_LENGTH - 1 downto 0); addr_i : in STD_LOGIC_VECTOR (8*g_ADDR_LENGTH - 1 downto 0);
data_i : in STD_LOGIC_VECTOR (8*g_DATA_LENGTH - 1 downto 0); data_i : in STD_LOGIC_VECTOR (8*g_DATA_LENGTH - 1 downto 0);
SPI0_i : in STD_LOGIC_VECTOR (31 downto 0); SPI0_i : in STD_LOGIC_VECTOR (31 downto 0);
SPI1_i : in STD_LOGIC_VECTOR (31 downto 0); SPI1_i : in STD_LOGIC_VECTOR (31 downto 0);
SPI2_o : out STD_LOGIC_VECTOR (15 downto 0); SPI2_o : out STD_LOGIC_VECTOR (15 downto 0);
spi_mosi_o : out STD_LOGIC; spi_mosi_o : out STD_LOGIC;
spi_miso_i : in STD_LOGIC; spi_miso_i : in STD_LOGIC;
spi_clk_o : out STD_LOGIC; spi_clk_o : out STD_LOGIC;
spi_cs_n_o : out STD_LOGIC spi_cs_n_o : out STD_LOGIC
); );
end spi_master_core; end spi_master_core;
...@@ -114,8 +132,26 @@ signal s_spi_clk_divider_oe_n : STD_LOGIC; ...@@ -114,8 +132,26 @@ signal s_spi_clk_divider_oe_n : STD_LOGIC;
signal s_spi_clk_manual_rst_i : STD_LOGIC; signal s_spi_clk_manual_rst_i : STD_LOGIC;
signal s_spi_clk_rst_i : STD_LOGIC; signal s_spi_clk_rst_i : STD_LOGIC;
signal s_manual_rst_spi_clk_fsm_i : STD_LOGIC; signal s_manual_rst_spi_clk_fsm_i : STD_LOGIC;
signal s_STATUS_pull_byte_already : STD_LOGIC; signal s_STATUS_pull_byte_already : STD_LOGIC;
signal s_spi_counter_manual_rst_clk_already : STD_LOGIC;
signal s_BINST : UNSIGNED (r_SPI0.BINST'length - 1 downto 0);
signal s_BADDR : UNSIGNED (r_SPI0.BADDR'length - 1 downto 0);
signal s_BDATA : UNSIGNED (r_SPI0.BDATA'length - 1 downto 0);
type r_cycle_sent_status_tmp is
record
SENT_INST : STD_LOGIC;
SENT_ADDR : STD_LOGIC;
SENT_DATA : STD_LOGIC;
end record;
signal s_cycle_status_tmp : r_cycle_sent_status_tmp;
constant c_cycle_status_tmp_default : r_cycle_sent_status_tmp := (SENT_INST => '0',
SENT_ADDR => '0',
SENT_DATA => '0'
);
begin begin
...@@ -129,8 +165,8 @@ begin ...@@ -129,8 +165,8 @@ begin
s_SPI1 <= f_SPI1(SPI1_i); s_SPI1 <= f_SPI1(SPI1_i);
SPI2_o <= f_STD_LOGIC_VECTOR(s_SPI2); SPI2_o <= f_STD_LOGIC_VECTOR(s_SPI2);
s_spi_counter_rst_i <= s_spi_counter_manual_rst_clk or rst_i; s_spi_counter_rst_i <= s_spi_counter_manual_rst_clk or rst_i;
s_timing_counter_rst_i <= s_timing_counter_manual_rst_i or rst_i; s_timing_counter_rst_i <= s_timing_counter_manual_rst_i or rst_i;
inst_fifo_i2c: FIFO_dispatcher inst_fifo_i2c: FIFO_dispatcher
generic map( generic map(
...@@ -213,10 +249,39 @@ begin ...@@ -213,10 +249,39 @@ begin
end if; end if;
end process; end process;
-----------------------------------------------------------
--! HW crop of bad BINST, BADDR and BDATA field configuration
-----------------------------------------------------------
p_crop_send_bytes :process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
s_BINST <= c_SPI0_default.BINST;
s_BADDR <= c_SPI0_default.BADDR;
s_BDATA <= c_SPI0_default.BDATA;
else
s_BINST <= c_SPI0_default.BINST;
s_BADDR <= c_SPI0_default.BADDR;
s_BDATA <= c_SPI0_default.BDATA;
if (to_integer(s_SPI0.BINST) <= c_SPI0_default.BINST) then
s_BINST <= s_SPI0.BINST;
end if;
if (to_integer(s_SPI0.BADDR) <= c_SPI0_default.BADDR) then
s_BADDR <= s_SPI0.BADDR;
end if;
if (to_integer(s_SPI0.BDATA) <= c_SPI0_default.BDATA) then
s_BDATA <= s_SPI0.BDATA;
end if;
end if;
else
end if;
end process;
----------------------------------------------------------- -----------------------------------------------------------
--! Process for pulling the FIFO contents right before --! WORK HERE
--! sending
----------------------------------------------------------- -----------------------------------------------------------
p_FIFO_pull_byte: process(clk_i) p_FIFO_pull_byte: process(clk_i)
begin begin
...@@ -225,33 +290,44 @@ begin ...@@ -225,33 +290,44 @@ begin
s_STATUS.PULL_INST <= c_STATUS_default.PULL_INST; s_STATUS.PULL_INST <= c_STATUS_default.PULL_INST;
s_STATUS.PULL_ADDR <= c_STATUS_default.PULL_ADDR; s_STATUS.PULL_ADDR <= c_STATUS_default.PULL_ADDR;
s_STATUS.PULL_DATA <= c_STATUS_default.PULL_DATA; s_STATUS.PULL_DATA <= c_STATUS_default.PULL_DATA;
s_STATUS_pull_byte_already <= '0';
else else
s_STATUS.PULL_INST <= c_STATUS_default.PULL_INST; s_STATUS.PULL_INST <= c_STATUS_default.PULL_INST;
s_STATUS.PULL_ADDR <= c_STATUS_default.PULL_ADDR; s_STATUS.PULL_ADDR <= c_STATUS_default.PULL_ADDR;
s_STATUS.PULL_DATA <= c_STATUS_default.PULL_DATA; s_STATUS.PULL_DATA <= c_STATUS_default.PULL_DATA;
if s_SPI1.SEND_OP = '1' then if s_SPI1.SEND_OP = '1' then
if ((s_STATUS.clk_fsm = S1_SETUP) and --! First prefetch for the first byte of the INST field.
not(to_integer(unsigned(s_timing_counter_cnt)) < c_CS_SU_TICKS)) if ( ( (s_STATUS.clk_fsm = S1_SETUP)
or ((s_STATUS.clk_fsm = S2_SPI_ACTIVITY) and and not(to_integer(unsigned(s_timing_counter_cnt)) < c_CS_SU_TICKS)))
(s_spi_counter_cnt(2 downto 0) = "000")) then or ( s_STATUS.clk_fsm = S2_SPI_ACTIVITY
if s_STATUS_pull_byte_already = '0' then and (s_spi_counter_cnt(2 downto 0) = "000")) then
s_STATUS_pull_byte_already <= '1';
if (s_SPI1.SEND_INST = '1') if s_STATUS_pull_byte_already = '0' then
and (s_STATUS.spi_clk_fsm = S1_INST) then s_STATUS_pull_byte_already <= '1';
s_STATUS.PULL_INST <= '1'; if (s_SPI1.SEND_INST = '1')
elsif (s_SPI1.SEND_ADDR = '1') and (s_STATUS.spi_clk_fsm = S1_INST or
and (s_STATUS.spi_clk_fsm = S2_ADDR) then s_STATUS.spi_clk_fsm = S0_IDLE) then
s_STATUS.PULL_ADDR <= '1'; s_STATUS.PULL_INST <= '1';
elsif (s_SPI1.SEND_DATA = '1') else
and (s_STATUS.spi_clk_fsm = S3_DATA) then end if;
s_STATUS.PULL_DATA <= '1'; if (s_SPI1.SEND_ADDR = '1')
else and (s_STATUS.spi_clk_fsm = S2_ADDR or
end if; ((s_SPI1.SEND_INST = '0') and
(s_STATUS.spi_clk_fsm = S0_IDLE))) then
s_STATUS.PULL_ADDR <= '1';
else else
end if; end if;
if (s_SPI1.SEND_DATA = '1')
and (s_STATUS.spi_clk_fsm = S3_DATA or
((s_SPI1.SEND_INST = '0') and
(s_SPI1.SEND_ADDR = '0') and
(s_STATUS.spi_clk_fsm = S0_IDLE))) then
s_STATUS.PULL_DATA <= '1';
else
end if;
else
end if;
else else
s_STATUS_pull_byte_already <= '0'; s_STATUS_pull_byte_already <= '0';
end if; end if;
else else
end if; end if;
...@@ -260,6 +336,66 @@ begin ...@@ -260,6 +336,66 @@ begin
end if; end if;
end process; end process;
-----------------------------------------------------------
--! Process for pulling the FIFO contents right before
--! sending
-----------------------------------------------------------
p_spi_counter_manual_rst: process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
s_spi_counter_manual_rst_clk <= '0';
s_spi_counter_manual_rst_clk_already <= '0';
s_cycle_status_tmp <= c_cycle_status_tmp_default;
else
s_spi_counter_manual_rst_clk <= '0';
if s_SPI1.SEND_OP = '1' then
if ((s_STATUS.clk_fsm = S1_SETUP) and not(to_integer(unsigned(s_timing_counter_cnt)) < c_CS_SU_TICKS))
or ((s_STATUS.clk_fsm = S2_SPI_ACTIVITY) and
(s_spi_counter_cnt(2 downto 0) = "000")) then
if s_spi_counter_manual_rst_clk_already = '0' then
s_spi_counter_manual_rst_clk_already <= '1';
if ( (s_SPI1.SEND_INST = '1')
and (s_cycle_status_tmp.SENT_INST = '0'))
and ((to_integer(s_SPI0.BINST) =
to_integer(unsigned(s_spi_counter_cnt(
c_COUNTER_DATA_WIDTH - 1 downto
3))))) then
s_cycle_status_tmp.SENT_INST <= '1';
s_spi_counter_manual_rst_clk <= '1';
elsif ( (s_SPI1.SEND_ADDR = '1')
and (s_cycle_status_tmp.SENT_ADDR = '0'))
and ((to_integer(s_SPI0.BADDR) =
to_integer(unsigned(s_spi_counter_cnt(
c_COUNTER_DATA_WIDTH - 1 downto
3))))) then
s_cycle_status_tmp.SENT_ADDR <= '1';
s_spi_counter_manual_rst_clk <= '1';
elsif ( (s_SPI1.SEND_DATA = '1')
and (s_cycle_status_tmp.SENT_DATA = '0'))
and ((to_integer(s_SPI0.BDATA) =
to_integer(unsigned(s_spi_counter_cnt(
c_COUNTER_DATA_WIDTH - 1 downto
3))))) then
s_cycle_status_tmp.SENT_DATA <= '1';
s_spi_counter_manual_rst_clk <= '1';
elsif (s_STATUS.spi_clk_fsm = Q0_END) then
s_spi_counter_manual_rst_clk <= '1';
else
end if;
else
end if;
else
s_spi_counter_manual_rst_clk_already <= '0';
end if;
else
s_cycle_status_tmp <= c_cycle_status_tmp_default;
end if;
end if;
else
end if;
end process;
----------------------------------------------------------- -----------------------------------------------------------
--! SPI mosi output --! SPI mosi output
----------------------------------------------------------- -----------------------------------------------------------
...@@ -293,29 +429,6 @@ begin ...@@ -293,29 +429,6 @@ begin
end if; end if;
end process; end process;
------------------------------------------------------------
--! Process for the reset of the SPI counter
------------------------------------------------------------
p_spi_counter_manual_rst: process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
s_spi_counter_manual_rst_clk <= '0';
else
s_spi_counter_manual_rst_clk <= '0';
if s_SPI1.SEND_OP = '1' then
if ((s_STATUS.clk_fsm = S1_SETUP) and
not(to_integer(unsigned(s_timing_counter_cnt)) < c_CS_SU_TICKS)) then
s_spi_counter_manual_rst_clk <= '1';
else
end if;
else
end if;
end if;
else
end if;
end process;
p_clk_fsm: process(clk_i) p_clk_fsm: process(clk_i)
begin begin
...@@ -349,9 +462,9 @@ begin ...@@ -349,9 +462,9 @@ begin
if s_SPI1.SEND_OP = '1' then if s_SPI1.SEND_OP = '1' then
case s_STATUS.clk_fsm is case s_STATUS.clk_fsm is
when S0_IDLE => when S0_IDLE =>
if (s_SPI1.SEND_INST = '1' and s_SPI0.BINST /= 0) if (s_SPI1.SEND_INST = '1' and s_BINST /= 0)
or (s_SPI1.SEND_ADDR = '1' and s_SPI0.BADDR /= 0) or (s_SPI1.SEND_ADDR = '1' and s_BADDR /= 0)
or (s_SPI1.SEND_DATA = '1' and s_SPI0.BDATA /= 0) then or (s_SPI1.SEND_DATA = '1' and s_BDATA /= 0) then
s_STATUS.clk_fsm <= S1_SETUP; s_STATUS.clk_fsm <= S1_SETUP;
s_timing_counter_en <= '1'; s_timing_counter_en <= '1';
else else
...@@ -450,9 +563,9 @@ begin ...@@ -450,9 +563,9 @@ begin
end if; end if;
when S1_INST => when S1_INST =>
if s_STATUS.clk_fsm = S2_SPI_ACTIVITY then if s_STATUS.clk_fsm = S2_SPI_ACTIVITY then
if to_integer(unsigned(s_spi_counter_cnt)) < if to_integer(unsigned(s_spi_counter_cnt))
to_integer(s_SPI0.BINST)*8 - 1 then < to_integer(s_BINST)*8 - 1 then
s_STATUS.spi_clk_fsm <= S1_INST; s_STATUS.spi_clk_fsm <= S1_INST;
else else
if s_SPI1.SEND_ADDR = '1' then if s_SPI1.SEND_ADDR = '1' then
s_STATUS.spi_clk_fsm <= S2_ADDR; s_STATUS.spi_clk_fsm <= S2_ADDR;
...@@ -466,9 +579,9 @@ begin ...@@ -466,9 +579,9 @@ begin
end if; end if;
when S2_ADDR => when S2_ADDR =>
if s_STATUS.clk_fsm = S2_SPI_ACTIVITY then if s_STATUS.clk_fsm = S2_SPI_ACTIVITY then
if to_integer(unsigned(s_spi_counter_cnt)) < if to_integer(unsigned(s_spi_counter_cnt))
to_integer(s_SPI0.BADDR)*8 - 1 then < to_integer(s_BADDR)*8 - 1 then
s_STATUS.spi_clk_fsm <= S2_ADDR; s_STATUS.spi_clk_fsm <= S2_ADDR;
else else
if s_SPI1.SEND_DATA = '1' then if s_SPI1.SEND_DATA = '1' then
s_STATUS.spi_clk_fsm <= S3_DATA; s_STATUS.spi_clk_fsm <= S3_DATA;
...@@ -480,9 +593,9 @@ begin ...@@ -480,9 +593,9 @@ begin
end if; end if;
when S3_DATA => when S3_DATA =>
if s_STATUS.clk_fsm = S2_SPI_ACTIVITY then if s_STATUS.clk_fsm = S2_SPI_ACTIVITY then
if to_integer(unsigned(s_spi_counter_cnt)) < if to_integer(unsigned(s_spi_counter_cnt))
to_integer(s_SPI0.BDATA)*8 - 1 then < to_integer(s_BDATA)*8 - 1 then
s_STATUS.spi_clk_fsm <= S3_DATA; s_STATUS.spi_clk_fsm <= S3_DATA;
else else
s_STATUS.spi_clk_fsm <= Q0_END; s_STATUS.spi_clk_fsm <= Q0_END;
end if; end if;
......
----------------------------------------------------------------------------------
-- --
-- Package File Template -- Copyright CERN 2011.
--
-- This documentation describes Open Hardware and is licensed under the
-- CERN OHL v. 1.1.
-- --
-- Purpose: This package defines supplemental types, subtypes, -- You may redistribute and modify this documentation under the terms of the CERN
-- constants, and functions -- OHL v.1.1. (http://ohwr.org/cernohl).
-- --
-- To use any of the example code shown below, uncomment the lines and modify as necessary -- This documentation is distributed WITHOUT
-- ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY
-- QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL v.1.1 for
-- applicable conditions.
-- --
----------------------------------------------------------------------------------
--
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 11:03:11 06/19/2012
-- Design Name:
-- Module Name: spi_master_pkg - Behavioral
-- Project Name: CTDAH/SVEC
-- Target Devices: Spartan 6
-- Tool versions: Xilinx ISE 13.4
-- Description: Package providing all the register configurations for the
-- SPI core.
--
-- Dependencies:
--
-- Revision: 0.1
-- 0.01 + File Created
-- 0.1 - Alpha version. Able to write and output data correctly at
-- different configurations.
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE; library IEEE;
use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_1164.all;
...@@ -133,24 +163,37 @@ package spi_master_pkg is ...@@ -133,24 +163,37 @@ package spi_master_pkg is
constant c_SPI0_addr : STD_LOGIC_VECTOR (3 downto 0) := X"0"; constant c_SPI0_addr : STD_LOGIC_VECTOR (3 downto 0) := X"0";
constant c_SPI1_addr : STD_LOGIC_VECTOR (3 downto 0) := X"1"; constant c_SPI1_addr : STD_LOGIC_VECTOR (3 downto 0) := X"1";
constant c_SPI2_addr : STD_LOGIC_VECTOR (3 downto 0) := X"2";
function f_SPI0 (signal r_register : in STD_LOGIC_VECTOR(31 downto 0)) return r_SPI0; function f_SPI0 (signal r_register : in STD_LOGIC_VECTOR(31 downto 0)) return r_SPI0;
function f_SPI1 (signal r_register : in STD_LOGIC_VECTOR(31 downto 0)) return r_SPI1; function f_SPI1 (signal r_register : in STD_LOGIC_VECTOR(31 downto 0)) return r_SPI1;
function f_SPI2 (signal r_register : in STD_LOGIC_VECTOR(15 downto 0)) return r_SPI2; function f_SPI2 (signal r_register : in STD_LOGIC_VECTOR(15 downto 0)) return r_SPI2;
function f_STD_LOGIC_VECTOR(signal r_register : in r_SPI0) return STD_LOGIC_VECTOR; function f_STD_LOGIC_VECTOR(r_register : in r_SPI0) return STD_LOGIC_VECTOR;
function f_STD_LOGIC_VECTOR(signal r_register : in r_SPI1) return STD_LOGIC_VECTOR; function f_STD_LOGIC_VECTOR(r_register : in r_SPI1) return STD_LOGIC_VECTOR;
function f_STD_LOGIC_VECTOR(signal r_register : in r_SPI2) return STD_LOGIC_VECTOR; function f_STD_LOGIC_VECTOR(r_register : in r_SPI2) return STD_LOGIC_VECTOR;
function f_min(a: NATURAL; b: NATURAL) return NATURAL;
end spi_master_pkg; end spi_master_pkg;
package body spi_master_pkg is package body spi_master_pkg is
function f_min(a: NATURAL; b: NATURAL) return NATURAL is
variable ret: NATURAL;
begin
if a < b then
ret := a;
else
ret := b;
end if;
return ret;
end f_min;
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
--! @brief SPI0 record type translation to STD_LOGIC_VECTOR --! @brief SPI0 record type translation to STD_LOGIC_VECTOR
--! @param r_register r_SPI0 record type to be translated --! @param r_register r_SPI0 record type to be translated
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function f_STD_LOGIC_VECTOR (signal r_register : in r_SPI0) return STD_LOGIC_VECTOR is function f_STD_LOGIC_VECTOR (r_register : in r_SPI0) return STD_LOGIC_VECTOR is
begin begin
return ( std_logic_vector(r_register.BINST) return ( std_logic_vector(r_register.BINST)
& std_logic_vector(r_register.BADDR) & std_logic_vector(r_register.BADDR)
...@@ -178,7 +221,7 @@ package body spi_master_pkg is ...@@ -178,7 +221,7 @@ package body spi_master_pkg is
--! @brief SPI1 record type translation to STD_LOGIC_VECTOR --! @brief SPI1 record type translation to STD_LOGIC_VECTOR
--! @param r_register r_CTR0 record type to be translated --! @param r_register r_CTR0 record type to be translated
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function f_STD_LOGIC_VECTOR (signal r_register : in r_SPI1) return STD_LOGIC_VECTOR is function f_STD_LOGIC_VECTOR (r_register : in r_SPI1) return STD_LOGIC_VECTOR is
begin begin
return ( r_register.z & std_logic_vector(r_register.CLK_DIV) return ( r_register.z & std_logic_vector(r_register.CLK_DIV)
& r_register.y & r_register.SEND_OP & r_register.y & r_register.SEND_OP
...@@ -216,7 +259,7 @@ package body spi_master_pkg is ...@@ -216,7 +259,7 @@ package body spi_master_pkg is
--! @brief SPI2 record type translation to STD_LOGIC_VECTOR --! @brief SPI2 record type translation to STD_LOGIC_VECTOR
--! @param r_register r_SPI2 record type to be translated --! @param r_register r_SPI2 record type to be translated
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
function f_STD_LOGIC_VECTOR (signal r_register : in r_SPI2) return STD_LOGIC_VECTOR is function f_STD_LOGIC_VECTOR (r_register : in r_SPI2) return STD_LOGIC_VECTOR is
begin begin
return ( std_logic_vector(r_register.CLK_DIV) return ( std_logic_vector(r_register.CLK_DIV)
& r_register.x & r_register.x
......
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
-- Company: --
-- Engineer: -- Copyright CERN 2011.
-- --
-- This documentation describes Open Hardware and is licensed under the
-- CERN OHL v. 1.1.
--
-- You may redistribute and modify this documentation under the terms of the CERN
-- OHL v.1.1. (http://ohwr.org/cernohl).
--
-- This documentation is distributed WITHOUT
-- ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY
-- QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL v.1.1 for
-- applicable conditions.
--
----------------------------------------------------------------------------------
--
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 17:34:08 06/14/2012 -- Create Date: 17:34:08 06/14/2012
-- Design Name: -- Design Name:
-- Module Name: spi_master_regs - Behavioral -- Module Name: spi_master_core - Behavioral
-- Project Name: -- Project Name: CTDAH/SVEC
-- Target Devices: -- Target Devices: Spartan 6
-- Tool versions: -- Tool versions: Xilinx ISE 13.4
-- Description: -- Description: Wishbone access for SPI core.
-- --
-- Dependencies: -- Dependencies:
-- --
-- Revision: -- Revision: 0.1
-- Revision 0.01 - File Created -- 0.01 + File Created
-- 0.1 - Alpha version. Able to write and output data correctly at
-- different configurations.
-- Additional Comments: -- Additional Comments:
-- --
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
library IEEE; library IEEE;
library work; library work;
use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_1164.ALL;
...@@ -40,7 +59,8 @@ entity spi_master_regs is ...@@ -40,7 +59,8 @@ entity spi_master_regs is
wb_err_o : out STD_LOGIC; wb_err_o : out STD_LOGIC;
SPI0_o : out STD_LOGIC_VECTOR (31 downto 0); SPI0_o : out STD_LOGIC_VECTOR (31 downto 0);
SPI1_o : out STD_LOGIC_VECTOR (31 downto 0) SPI1_o : out STD_LOGIC_VECTOR (31 downto 0);
SPI2_i : in STD_LOGIC_VECTOR (15 downto 0)
); );
end spi_master_regs; end spi_master_regs;
...@@ -48,6 +68,7 @@ architecture Behavioral of spi_master_regs is ...@@ -48,6 +68,7 @@ architecture Behavioral of spi_master_regs is
signal s_SPI0 : STD_LOGIC_VECTOR (31 downto 0); signal s_SPI0 : STD_LOGIC_VECTOR (31 downto 0);
signal s_SPI1 : STD_LOGIC_VECTOR (31 downto 0); signal s_SPI1 : STD_LOGIC_VECTOR (31 downto 0);
signal s_SPI2 : STD_LOGIC_VECTOR (15 downto 0);
signal s_wb_ack : STD_LOGIC; signal s_wb_ack : STD_LOGIC;
signal s_wb_rty : STD_LOGIC; signal s_wb_rty : STD_LOGIC;
...@@ -61,11 +82,14 @@ begin ...@@ -61,11 +82,14 @@ begin
SPI0_o <= s_SPI0; SPI0_o <= s_SPI0;
SPI1_o <= s_SPI1; SPI1_o <= s_SPI1;
s_SPI2 <= SPI2_i;
p_wb: process (wb_clk_i) p_wb: process (wb_clk_i)
begin begin
if rising_edge(wb_clk_i) then if rising_edge(wb_clk_i) then
if wb_rst_i = '1' then if wb_rst_i = '1' then
s_SPI0 <= f_STD_LOGIC_VECTOR(c_SPI0_default);
s_SPI1 <= f_STD_LOGIC_VECTOR(c_SPI1_default);
elsif (wb_stb_i = '1' and wb_cyc_i = '1') then elsif (wb_stb_i = '1' and wb_cyc_i = '1') then
if (s_wb_ack or s_wb_rty or s_wb_err) = '1' then if (s_wb_ack or s_wb_rty or s_wb_err) = '1' then
s_wb_ack <= '0'; s_wb_ack <= '0';
...@@ -95,7 +119,11 @@ begin ...@@ -95,7 +119,11 @@ begin
when c_SPI1_addr => when c_SPI1_addr =>
wb_data_o <= s_SPI1; wb_data_o <= s_SPI1;
s_wb_ack <= '1'; s_wb_ack <= '1';
when others => when c_SPI2_addr =>
wb_data_o(15 downto 0) <= s_SPI2;
wb_data_o(31 downto 16) <= (others => '0');
s_wb_ack <= '1';
when others =>
end case; end case;
end case; end case;
end if; end if;
......
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
--
-- Copyright CERN 2011.
--
-- This documentation describes Open Hardware and is licensed under the
-- CERN OHL v. 1.1.
--
-- You may redistribute and modify this documentation under the terms of the CERN
-- OHL v.1.1. (http://ohwr.org/cernohl).
--
-- This documentation is distributed WITHOUT
-- ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY
-- QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL v.1.1 for
-- applicable conditions.
--
----------------------------------------------------------------------------------
--
-- Company: CERN, BE-CO-HT -- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano -- Engineer: Carlos Gil Soriano
-- --
...@@ -13,11 +29,14 @@ ...@@ -13,11 +29,14 @@
-- --
-- Dependencies: -- Dependencies:
-- --
-- Revision: -- Revision: 0.1
-- Revision 0.01 - File Created -- 0.01 + File Created
-- 0.1 - Alpha version. Able to write and output data correctly at
-- different configurations.
-- Additional Comments: -- Additional Comments:
-- --
---------------------------------------------------------------------------------- ----------------------------------------------------------------------------------
library IEEE; library IEEE;
library work; library work;
use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_1164.ALL;
...@@ -96,7 +115,8 @@ architecture Behavioral of spi_master_top is ...@@ -96,7 +115,8 @@ architecture Behavioral of spi_master_top is
wb_err_o : out STD_LOGIC; wb_err_o : out STD_LOGIC;
SPI0_o : out STD_LOGIC_VECTOR (31 downto 0); SPI0_o : out STD_LOGIC_VECTOR (31 downto 0);
SPI1_o : out STD_LOGIC_VECTOR (31 downto 0) SPI1_o : out STD_LOGIC_VECTOR (31 downto 0);
SPI2_i : in STD_LOGIC_VECTOR (15 downto 0)
); );
end component; end component;
...@@ -142,7 +162,8 @@ begin ...@@ -142,7 +162,8 @@ begin
wb_err_o => wb_err_o, wb_err_o => wb_err_o,
SPI0_o => s_SPI0, SPI0_o => s_SPI0,
SPI1_o => s_SPI1 SPI1_o => s_SPI1,
SPI2_i => s_SPI2
); );
end Behavioral; end Behavioral;
......
--------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 12:31:47 06/20/2012
-- Design Name:
-- Module Name: /media/BACKUP/CERN/contrib/ohwr/conv-ttl-blo/hdl/spi_master_multifield/test/spi_master_core_tb.vhd
-- Project Name: spi_master_multifield
-- Target Device:
-- Tool versions:
-- Description:
--
-- VHDL Test Bench Created by ISE for module: spi_master_core
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes:
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation
-- simulation model.
--------------------------------------------------------------------------------
library IEEE;
library work;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.spi_master_pkg.ALL;
entity spi_master_core_tb is
end spi_master_core_tb;
architecture behavior of spi_master_core_tb is
-- Component Declaration for the Unit Under Test (UUT)
component spi_master_core
port(
rst_i : in STD_LOGIC;
clk_i : in STD_LOGIC;
inst_i : in STD_LOGIC_VECTOR (8*c_INST_LENGTH - 1 downto 0);
addr_i : in STD_LOGIC_VECTOR (8*c_ADDR_LENGTH - 1 downto 0);
data_i : in STD_LOGIC_VECTOR (8*c_DATA_LENGTH - 1 downto 0);
SPI0_i : in STD_LOGIC_VECTOR (31 downto 0);
SPI1_i : in STD_LOGIC_VECTOR (31 downto 0);
SPI2_o : out STD_LOGIC_VECTOR (15 downto 0);
spi_mosi_o : out STD_LOGIC;
spi_miso_i : in STD_LOGIC;
spi_clk_o : out STD_LOGIC;
spi_cs_n_o : out STD_LOGIC
);
end component;
--Inputs
signal rst_i : STD_LOGIC := '0';
signal clk_i : STD_LOGIC := '0';
signal inst_i : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal addr_i : STD_LOGIC_VECTOR (23 downto 0) := (others => '0');
signal data_i : STD_LOGIC_VECTOR (2047 downto 0) := (others => '0');
signal inst_check : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
signal addr_check : STD_LOGIC_VECTOR (23 downto 0) := (others => '0');
signal data_check : STD_LOGIC_VECTOR (2047 downto 0) := (others => '0');
signal SPI0_i : STD_LOGIC_VECTOR (31 downto 0) := (others => '0');
signal SPI1_i : STD_LOGIC_VECTOR (31 downto 0) := (others => '0');
signal SPI2_o : STD_LOGIC_VECTOR (15 downto 0);
signal s_SPI0 : r_SPI0;
signal s_SPI1 : r_SPI1;
signal s_SPI2 : r_SPI2;
signal spi_miso_i : STD_LOGIC := '0';
--Outputs
signal spi_mosi_o : STD_LOGIC;
signal spi_clk_o : STD_LOGIC;
signal spi_cs_n_o : STD_LOGIC;
signal s_spi_count : NATURAL;
signal s_rst_spi_analyser : STD_LOGIC;
signal s_end_inst_flag : STD_LOGIC;
signal s_end_addr_flag : STD_LOGIC;
signal s_end_data_flag : STD_LOGIC;
-- Clock period definitions
constant c_WISHBONE_PERIOD : TIME := 10 ns;
-- file file_handler : TEXT;
-- constant log_path : STRING := "../test/log/spi_master_core_tb.log";
-- constant sep : CHARACTER := ht;
begin
SPI0_i <= f_STD_LOGIC_VECTOR(s_SPI0);
SPI1_i <= f_STD_LOGIC_VECTOR(s_SPI1);
s_SPI2 <= f_SPI2(SPI2_o);
-- Instantiate the Unit Under Test (UUT)
uut: spi_master_core port map (
rst_i => rst_i,
clk_i => clk_i,
inst_i => inst_i,
addr_i => addr_i,
data_i => data_i,
SPI0_i => SPI0_i,
SPI1_i => SPI1_i,
SPI2_o => SPI2_o,
spi_mosi_o => spi_mosi_o,
spi_miso_i => spi_miso_i,
spi_clk_o => spi_clk_o,
spi_cs_n_o => spi_cs_n_o
);
-- Clock process definitions
clk_i_process :process
begin
clk_i <= '0';
wait for c_WISHBONE_PERIOD/2;
clk_i <= '1';
wait for c_WISHBONE_PERIOD/2;
end process;
spi_analyser: process(spi_clk_o, s_rst_spi_analyser)
variable v_inst_length : NATURAL;
variable v_addr_length : NATURAL;
variable v_data_length : NATURAL;
begin
if s_rst_spi_analyser = '1' then
s_spi_count <= 0;
else
if rising_edge(spi_clk_o) then
--! This is the equivalent to the HW crop in spi_master_core
v_inst_length := f_min(to_integer(s_SPI0.BINST), c_INST_LENGTH)*8;
v_addr_length := f_min(to_integer(s_SPI0.BADDR), c_ADDR_LENGTH)*8;
v_data_length := f_min(to_integer(s_SPI0.BDATA), c_DATA_LENGTH)*8;
s_spi_count <= s_spi_count + 1;
s_end_inst_flag <= '0';
s_end_addr_flag <= '0';
s_end_data_flag <= '0';
if s_SPI1.SEND_INST = '1' then
if s_spi_count < v_inst_length then
inst_check(v_inst_length - 1 - s_spi_count) <= spi_mosi_o;
if s_spi_count = (v_inst_length - 1) then
if s_end_inst_flag = '0' then
s_end_inst_flag <= '1';
end if;
end if;
else
end if;
else
end if;
if s_SPI1.SEND_ADDR = '1' then
if s_SPI1.SEND_INST = '1' then
if s_spi_count >= v_inst_length
and s_spi_count < (v_inst_length + v_addr_length) then
addr_check(v_addr_length - 1 - (s_spi_count -
v_inst_length)) <= spi_mosi_o;
if s_spi_count = (v_inst_length + v_addr_length - 1) then
if s_end_addr_flag = '0' then
s_end_addr_flag <= '1';
end if;
end if;
else
end if;
else
if s_spi_count < v_addr_length then
addr_check(v_addr_length - 1 - s_spi_count) <= spi_mosi_o;
if s_spi_count = (v_addr_length - 1) then
if s_end_addr_flag = '0' then
s_end_addr_flag <= '1';
end if;
end if;
else
end if;
end if;
else
end if;
if s_SPI1.SEND_DATA = '1' then
if s_SPI1.SEND_INST = '1' then
if s_SPI1.SEND_ADDR = '1' then
if s_spi_count >= (v_inst_length + v_addr_length) then
data_check(v_data_length - 1 - (s_spi_count - v_inst_length
- v_addr_length)) <= spi_mosi_o;
if s_spi_count = (v_inst_length + v_addr_length + v_data_length - 1) then
if s_end_data_flag = '0' then
s_end_data_flag <= '1';
end if;
end if;
else
end if;
else
if s_spi_count >= v_inst_length then
data_check(v_data_length - 1 - (s_spi_count -
v_inst_length)) <= spi_mosi_o;
if s_spi_count = (v_inst_length + v_data_length - 1) then
if s_end_data_flag = '0' then
s_end_data_flag <= '1';
end if;
end if;
else
end if;
end if;
else
if s_SPI1.SEND_ADDR = '1' then
if s_spi_count >= v_addr_length then
data_check(v_data_length - 1 - (s_spi_count -
v_addr_length)) <= spi_mosi_o;
if s_spi_count = (v_addr_length + v_data_length - 1) then
if s_end_data_flag = '0' then
s_end_data_flag <= '1';
end if;
end if;
else
end if;
else
if s_spi_count = (v_data_length - 1) then
if s_end_data_flag = '0' then
s_end_data_flag <= '1';
end if;
end if;
data_check(s_spi_count) <= spi_mosi_o;
end if;
end if;
else
end if;
else
end if;
end if;
end process;
-- Stimulus process
stim_proc: process
procedure init_cond is
begin
inst_i <= (others => '0');
addr_i <= (others => '0');
data_i <= (others => '0');
s_SPI0 <= c_SPI0_default;
s_SPI1 <= c_SPI1_default;
end procedure;
procedure set_FIFO_contents(inst: STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
addr: STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
data: STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0)) is
begin
inst_i <= inst;
addr_i <= addr;
data_i <= data;
wait until rising_edge(clk_i);
s_SPI1.PUSH_INST <= '1';
s_SPI1.PUSH_ADDR <= '1';
s_SPI1.PUSH_DATA <= '1';
wait until rising_edge(clk_i);
s_SPI1.PUSH_INST <= '0';
s_SPI1.PUSH_ADDR <= '0';
s_SPI1.PUSH_DATA <= '0';
end procedure;
procedure set_spi_lengths(inst_length: NATURAL;
addr_length: NATURAL;
data_length: NATURAL) is
begin
s_SPI0 <= (x => (others => '0'),
BDATA => to_unsigned(data_length, s_SPI0.BDATA'length),
BADDR => to_unsigned(addr_length, s_SPI0.BADDR'length),
BINST => to_unsigned(inst_length, s_SPI0.BINST'length));
end procedure;
procedure send_SPI_and_wait(send_inst: STD_LOGIC;
send_addr: STD_LOGIC;
send_data: STD_LOGIC) is
begin
s_SPI1.SEND_INST <= '0';
s_SPI1.SEND_ADDR <= '0';
s_SPI1.SEND_DATA <= '0';
wait until rising_edge(clk_i);
if send_inst = '1' then
s_SPI1.SEND_INST <= '1';
end if;
if send_addr = '1' then
s_SPI1.SEND_ADDR <= '1';
end if;
if send_data = '1' then
s_SPI1.SEND_DATA <= '1';
end if;
s_SPI1.SEND_OP <= '1';
wait until s_SPI2.SENT_OP = '1';
s_SPI1.SEND_OP <= '0';
s_SPI1.SEND_INST <= '0';
s_SPI1.SEND_ADDR <= '0';
s_SPI1.SEND_DATA <= '0';
end procedure;
-- procedure assert_to_file(data : STD_LOGIC_VECTOR(31 downto 0);
-- reference : STD_LOGIC_VECTOR(31 downto 0);
-- test_id : STRING;
-- msg : STRING) is
-- variable line_buffer : LINE;
-- begin
-- if data = reference then
-- write(line_buffer, string'(test_id&sep&"OK"&sep&msg));
-- else
-- write(line_buffer, string'(test_id&sep&"Fail"&sep&msg));
-- end if;
-- writeline(file_handler, line_buffer);
-- assert data = reference report "Bad"&msg;
-- end procedure;
procedure spi_command(inst_length: NATURAL; addr_length: NATURAL; data_length: NATURAL;
send_inst : STD_LOGIC; send_addr: STD_LOGIC; send_data: STD_LOGIC;
inst : STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
addr : STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
data : STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0)) is
begin
s_rst_spi_analyser <= '1';
wait until rising_edge(clk_i);
s_rst_spi_analyser <= '0';
wait until rising_edge(clk_i);
set_FIFO_contents(inst, addr, data);
set_spi_lengths(inst_length, addr_length, data_length);
send_SPI_and_wait(send_inst, send_addr, send_data);
end procedure;
begin
init_cond;
wait until rising_edge(clk_i);
wait for c_WISHBONE_PERIOD*10;
rst_i <= '1';
wait for c_WISHBONE_PERIOD*10;
rst_i <= '0';
wait for c_WISHBONE_PERIOD*10;
set_FIFO_contents(X"AB", X"123456", (others => '0'));
inst_i <= X"AB";
addr_i <= X"123456";
data_i <= (others => '0');
spi_command( 1, 1, 1,
'1', '1', '1',
inst_i, addr_i, data_i);
wait for c_WISHBONE_PERIOD*10;
spi_command( 1, 3, 256,
'1', '1', '1',
inst_i, addr_i, data_i);
wait for c_WISHBONE_PERIOD*10;
spi_command( 1, 0, 0,
'1', '0', '0',
inst_i, addr_i, data_i);
wait for c_WISHBONE_PERIOD*10;
spi_command( 1, 3, 1,
'0', '1', '0',
inst_i, addr_i, data_i);
wait for c_WISHBONE_PERIOD*10;
spi_command( 1, 1, 2,
'0', '0', '1',
inst_i, addr_i, data_i);
wait for c_WISHBONE_PERIOD*10;
wait;
end process;
END;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment