- Master RX and TX working

git-svn-id: http://moon:8086/svn/vhdl/trunk@1276 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2015-06-04 11:09:56 +00:00
parent 7ad5c7f3c2
commit 6605ecc2ac
5 changed files with 405 additions and 143 deletions
+1 -1
View File
@@ -22,4 +22,4 @@ do {tb_spi.wdo}
view structure view structure
view signals view signals
run 20 us run 60 us
+30 -20
View File
@@ -2,15 +2,26 @@ onerror {resume}
quietly WaveActivateNextPane {} 0 quietly WaveActivateNextPane {} 0
add wave -noupdate -format Logic /tb_spi/clk add wave -noupdate -format Logic /tb_spi/clk
add wave -noupdate -format Logic /tb_spi/rst add wave -noupdate -format Logic /tb_spi/rst
add wave -noupdate -format Logic /tb_spi/tx_cmd_vld add wave -noupdate -format Logic /tb_spi/mst_cmd_vld
add wave -noupdate -format Logic /tb_spi/tx_cmd_rdy add wave -noupdate -format Logic /tb_spi/mst_cmd_rdy
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/tx_cmd add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_cmd
add wave -noupdate -format Logic /tb_spi/tx_din_vld add wave -noupdate -format Logic /tb_spi/mst_din_vld
add wave -noupdate -format Logic /tb_spi/tx_din_rdy add wave -noupdate -format Logic /tb_spi/mst_din_rdy
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/tx_din add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_din
add wave -noupdate -format Logic /tb_spi/tx_shift_en add wave -noupdate -format Logic /tb_spi/mst_shift_en
add wave -noupdate -format Logic /tb_spi/tx_mosi add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_dout
add wave -noupdate -format Logic /tb_spi/tx_clk add wave -noupdate -format Logic /tb_spi/mst_dout_vld
add wave -noupdate -format Logic /tb_spi/mst_dout_re
add wave -noupdate -format Logic /tb_spi/mosi
add wave -noupdate -format Logic /tb_spi/miso
add wave -noupdate -format Logic /tb_spi/mst_clk
add wave -noupdate -format Logic /tb_spi/mso
add wave -noupdate -format Literal /tb_spi/ctrl
add wave -noupdate -format Literal -expand /tb_spi/status
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/slv_rx_shiftreg
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/slv_rx_valid_pipe
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/slv_rx_data
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_rx_data
add wave -noupdate -divider TX add wave -noupdate -divider TX
add wave -noupdate -format Literal /tb_spi/inst_spi_tx/word_width add wave -noupdate -format Literal /tb_spi/inst_spi_tx/word_width
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/rst add wave -noupdate -format Logic /tb_spi/inst_spi_tx/rst
@@ -22,30 +33,29 @@ add wave -noupdate -format Logic /tb_spi/inst_spi_tx/din_vld
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/din_rdy add wave -noupdate -format Logic /tb_spi/inst_spi_tx/din_rdy
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/din add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/din
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/shift_en add wave -noupdate -format Logic /tb_spi/inst_spi_tx/shift_en
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/data_out add wave -noupdate -format Logic /tb_spi/inst_spi_tx/mosi
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/shift_reg add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/tx_shift_reg
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/clk_out add wave -noupdate -format Logic /tb_spi/inst_spi_tx/sclk
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/xfer_count add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/xfer_count
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/data_count
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/word_count
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cmd_reg add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cmd_reg
add wave -noupdate -format Literal /tb_spi/inst_spi_tx/state add wave -noupdate -format Literal /tb_spi/inst_spi_tx/state
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/data_load_en add wave -noupdate -format Logic /tb_spi/inst_spi_tx/data_load_en
add wave -noupdate -format Literal /tb_spi/inst_spi_tx/shift_cnt_pipe add wave -noupdate -format Literal /tb_spi/inst_spi_tx/shift_cnt_pipe
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cmd_reg_we
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/xfer_count_en add wave -noupdate -format Logic /tb_spi/inst_spi_tx/xfer_count_en
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/data_count_en
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/xfer_count_busy add wave -noupdate -format Logic /tb_spi/inst_spi_tx/xfer_count_busy
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/data_count
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/data_count_busy add wave -noupdate -format Logic /tb_spi/inst_spi_tx/data_count_busy
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/spi_clk add wave -noupdate -format Logic /tb_spi/inst_spi_tx/spi_clk
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cat_fifo_din add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cat_fifo_din
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cat_fifo_dout add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cat_fifo_dout
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cat_fifo_re
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cat_fifo_we
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cat_fifo_full add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cat_fifo_full
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cat_fifo_empty add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cat_fifo_empty
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/write_fifo_din
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/write_fifo_dout
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/write_fifo_full
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/write_fifo_empty
TreeUpdate [SetDefaultTree] TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {6254805 ps} 0} WaveRestoreCursors {{Cursor 1} {17474865 ps} 0}
configure wave -namecolwidth 197 configure wave -namecolwidth 197
configure wave -valuecolwidth 131 configure wave -valuecolwidth 131
configure wave -justifyvalue left configure wave -justifyvalue left
@@ -59,4 +69,4 @@ configure wave -gridperiod 1
configure wave -griddelta 40 configure wave -griddelta 40
configure wave -timeline 0 configure wave -timeline 0
update update
WaveRestoreZoom {5843806 ps} {8445242 ps} WaveRestoreZoom {0 ps} {63 us}
+196 -87
View File
@@ -23,64 +23,84 @@ ENTITY spi_tx IS
din_vld : in STD_LOGIC; din_vld : in STD_LOGIC;
din_rdy : out STD_LOGIC; din_rdy : out STD_LOGIC;
din : in unsigned(word_width-1 downto 0); din : in unsigned(word_width-1 downto 0);
dout : out unsigned(word_width-1 downto 0);
dout_vld : out STD_LOGIC;
dout_re : in STD_LOGIC;
shift_en : in STD_LOGIC; shift_en : in STD_LOGIC;
data_out : out STD_LOGIC;
clk_out : out STD_LOGIC;
ctrl : in ctrl_t; ctrl : in ctrl_t;
status : out status_t status : out status_t;
mosi : out STD_LOGIC;
miso : in STD_LOGIC;
sclk : out STD_LOGIC;
mso : out STD_LOGIC
); );
END spi_tx; END spi_tx;
ARCHITECTURE behavior OF spi_tx IS ARCHITECTURE behavior OF spi_tx IS
type state_t is (idle, prepare, shift, finish); type state_t is (reset, idle, load_data, shift, finish);
signal xfer_count : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); signal xfer_count : unsigned(XFER_MAX_SIZE_BITS-1 downto 0);
signal data_count : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); signal data_count : unsigned(XFER_MAX_SIZE_BITS-1 downto 0);
signal word_count : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); signal cmd_reg : cmd_t;
signal cmd_reg : cmd_t; signal state : state_t;
signal state : state_t; signal state_next : state_t;
signal state_next : state_t; signal xfer_count_en : std_logic;
signal cmd_reg_we : std_logic; signal xfer_count_busy : std_logic;
signal xfer_count_en : std_logic; signal data_count_busy : std_logic;
signal data_count_en : std_logic; signal spi_clk : std_logic := '0';
signal xfer_count_busy : std_logic; signal spi_clk_out : std_logic;
signal data_count_busy : std_logic; signal clk_en : std_logic;
signal spi_clk : std_logic := '0'; signal spi_clk_data : std_logic;
signal spi_clk_out : std_logic := '0'; signal spi_rst_count : unsigned(5 downto 0);
signal clk_en : std_logic; signal spi_rst : std_logic;
signal cat_fifo_din : unsigned(to_unsigned(cmd)'length-1 downto 0); signal cat_fifo_din : unsigned(to_unsigned(cmd)'length-1 downto 0);
signal cat_fifo_dout : unsigned(to_unsigned(cmd)'length-1 downto 0); signal cat_fifo_dout : unsigned(to_unsigned(cmd)'length-1 downto 0);
signal cat_fifo_re : std_logic;
signal cat_fifo_we : std_logic;
signal cat_fifo_full : std_logic; signal cat_fifo_full : std_logic;
signal cat_fifo_empty : std_logic; signal cat_fifo_empty : std_logic;
signal write_fifo_din : unsigned(word_width-1 downto 0); signal write_fifo_din : unsigned(word_width-1 downto 0);
signal write_fifo_dout : unsigned(word_width-1 downto 0); signal write_fifo_dout : unsigned(word_width-1 downto 0);
signal write_fifo_re : std_logic;
signal write_fifo_we : std_logic;
signal write_fifo_full : std_logic; signal write_fifo_full : std_logic;
signal write_fifo_empty : std_logic; signal write_fifo_empty : std_logic;
signal shift_reg : unsigned(word_width-1 downto 0); signal read_fifo_din : unsigned(word_width-1 downto 0);
signal read_fifo_dout : unsigned(word_width-1 downto 0);
signal read_fifo_full : std_logic;
signal read_fifo_empty : std_logic;
signal read_fifo_we : std_logic;
signal tx_shift_reg : unsigned(word_width-1 downto 0);
signal rx_shift_reg : unsigned(word_width-1 downto 0);
signal shift_cnt_pipe : unsigned(word_width-1 downto 0); signal shift_cnt_pipe : unsigned(word_width-1 downto 0);
signal data_load_en : std_logic; signal data_load_en : std_logic;
signal xfer_start_en : std_logic;
signal ctrl_reg : ctrl_t;
signal rx_enable : std_logic;
signal slv_enable : std_logic;
-------------------------------------------------------------------------- --------------------------------------------------------------------------
begin begin
clk_out <= spi_clk_out; sclk <= spi_clk_out;
cat_fifo_din <= to_unsigned(cmd); cat_fifo_din <= to_unsigned(cmd);
write_fifo_din <= din; write_fifo_din <= din;
cmd_rdy <= not cat_fifo_full; cmd_reg <= to_cmd(cat_fifo_dout);
din_rdy <= not write_fifo_full; mosi <= tx_shift_reg(tx_shift_reg'left) when ctrl_reg.msb_first = '1' else tx_shift_reg(tx_shift_reg'right);
cat_fifo_we <= cmd_vld; spi_clk_data <= spi_clk xor ctrl_reg.cpha;
cmd_reg <= to_cmd(cat_fifo_dout);
data_out <= shift_reg(shift_reg'left) when ctrl.msb_first = '1' else shift_reg(shift_reg'right); dout_vld <= not read_fifo_empty;
data_load_en <= not data_count_en or shift_cnt_pipe(shift_cnt_pipe'left-1); status.cmd_fifo_full <= cat_fifo_full;
status.cmd_fifo_empty <= cat_fifo_empty;
status.write_fifo_full <= write_fifo_full;
status.write_fifo_empty <= write_fifo_empty;
status.read_fifo_full <= read_fifo_full;
status.read_fifo_empty <= read_fifo_empty;
status.rx_valid <= read_fifo_we;
mso <= slv_enable;
rx_enable <= '1' when cmd_reg.xfer_size > cmd_reg.data_size else '0';
-------------------------------------------------------------------------- --------------------------------------------------------------------------
-- Instantiate synchronous FIFO -- Instantiate synchronous FIFO
@@ -92,11 +112,11 @@ begin
) )
PORT MAP PORT MAP
( (
rst => rst, rst => spi_rst,
clk_w => clk, clk_w => clk,
clk_r => spi_clk, clk_r => spi_clk,
we => cat_fifo_we, we => cmd_vld,
re => cat_fifo_re, re => xfer_start_en,
fifo_full => cat_fifo_full, fifo_full => cat_fifo_full,
fifo_empty => cat_fifo_empty, fifo_empty => cat_fifo_empty,
fifo_afull => open, fifo_afull => open,
@@ -114,11 +134,11 @@ begin
) )
PORT MAP PORT MAP
( (
rst => rst, rst => spi_rst,
clk_w => clk, clk_w => clk,
clk_r => spi_clk, clk_r => spi_clk,
we => din_vld, we => din_vld,
re => write_fifo_re, re => data_load_en,
fifo_full => write_fifo_full, fifo_full => write_fifo_full,
fifo_empty => write_fifo_empty, fifo_empty => write_fifo_empty,
fifo_afull => open, fifo_afull => open,
@@ -127,12 +147,45 @@ begin
data_r => write_fifo_dout data_r => write_fifo_dout
); );
-- Instantiate synchronous FIFO
inst_read_fifo: entity work.fifo_async
GENERIC MAP
(
addr_width => NextExpBaseTwo(DATA_FIFO_DEPTH),
data_width => word_width
)
PORT MAP
(
rst => spi_rst,
clk_w => clk,
clk_r => spi_clk,
we => read_fifo_we,
re => dout_re,
fifo_full => read_fifo_full,
fifo_empty => read_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => rx_shift_reg,
data_r => dout
);
-------------------------------------------------------------------------- --------------------------------------------------------------------------
proc_spi_clk_gen: proc_spi_clk_gen:
process(clk) process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
spi_clk <= not spi_clk; if rst = '1' then
spi_rst <= '1';
spi_clk <= '0';
spi_rst_count <= (others => '1');
else
spi_clk <= not spi_clk;
if spi_rst_count /= to_unsigned(0, spi_rst_count'length) then
spi_rst_count <= spi_rst_count - 1;
else
spi_rst <= '0';
end if;
end if ;
end if; end if;
end process; end process;
@@ -140,10 +193,10 @@ proc_spi_clk_out_gen:
process(clk) process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if rst = '1' then if spi_rst = '1' then
spi_clk_out <= '0'; spi_clk_out <= '0';
elsif clk_en = '0' then elsif clk_en = '0' then
spi_clk_out <= ctrl.polarity; spi_clk_out <= ctrl_reg.cpol;
else else
spi_clk_out <= not spi_clk_out; spi_clk_out <= not spi_clk_out;
end if; end if;
@@ -154,49 +207,78 @@ proc_state_next:
process(spi_clk) process(spi_clk)
begin begin
if rising_edge(spi_clk) then if rising_edge(spi_clk) then
if rst = '1' then if spi_rst = '1' then
state <= idle; state <= reset;
else else
state <= state_next; state <= state_next;
end if; end if;
end if; end if;
end process; end process;
proc_ctrl_reg:
process(spi_clk)
begin
if rising_edge(spi_clk) then
if xfer_start_en = '1' or spi_rst = '1' then
ctrl_reg <= ctrl;
end if;
end if;
end process;
proc_fsm: proc_fsm:
process(state, cat_fifo_empty, xfer_count_busy) process(state, rx_enable, cat_fifo_empty, cat_fifo_full, write_fifo_empty, write_fifo_full, xfer_count_busy, data_count_busy, shift_cnt_pipe, ctrl_reg)
begin begin
state_next <= state; state_next <= state;
cmd_reg_we <= '0';
cat_fifo_re <= '0'; xfer_start_en <= '0';
xfer_count_en <= '0'; xfer_count_en <= '0';
data_count_en <= '0'; data_load_en <= '0';
clk_en <= '0'; clk_en <= '0';
cmd_rdy <= not cat_fifo_full;
din_rdy <= not write_fifo_full;
slv_enable <= '1';
read_fifo_we <= '0';
case state is case state is
when reset =>
cmd_rdy <= '0';
din_rdy <= '0';
slv_enable <= '0';
state_next <= idle;
when idle => when idle =>
slv_enable <= '0';
if cat_fifo_empty = '0' then if cat_fifo_empty = '0' then
cmd_reg_we <= '1'; state_next <= load_data;
state_next <= prepare; xfer_start_en <= '1';
end if; end if;
when prepare => when load_data =>
cat_fifo_re <= '1'; if xfer_count_busy = '0' then
write_fifo_re <= '1'; state_next <= idle;
clk_en <= '1'; elsif write_fifo_empty = '0' then
xfer_count_en <= '1'; data_load_en <= '1';
data_count_en <= '1'; state_next <= shift;
state_next <= shift; clk_en <= ctrl_reg.cpha;
end if;
when shift => when shift =>
clk_en <= '1'; clk_en <= '1';
xfer_count_en <= '1'; xfer_count_en <= '1';
data_count_en <= '1';
if xfer_count_busy = '0' then if xfer_count_busy = '0' then
state_next <= finish; state_next <= finish;
elsif shift_cnt_pipe(shift_cnt_pipe'left) = '1' and data_count_busy = '1' then
if write_fifo_empty = '0' then
data_load_en <= '1';
else
state_next <= load_data;
end if;
end if; end if;
when finish => when finish =>
state_next <= idle; read_fifo_we <= rx_enable;
state_next <= idle;
when others => when others =>
state_next <= idle; state_next <= idle;
@@ -204,15 +286,15 @@ begin
end case; end case;
end process; end process;
PROC_XFER_COUNT:
process(spi_clk) process(spi_clk)
begin begin
if rising_edge(spi_clk) then if rising_edge(spi_clk) then
if xfer_count_en = '0' then if xfer_start_en = '1' then
xfer_count <= cmd_reg.xfer_size; xfer_count <= cmd_reg.xfer_size;
xfer_count_busy <= '0'; xfer_count_busy <= '1';
elsif shift_en = '1' then elsif shift_en = '1' and xfer_count_en = '1' then
if xfer_count /= to_unsigned(0, xfer_count'length) then if xfer_count /= to_unsigned(2, xfer_count'length) then
xfer_count_busy <= '1';
xfer_count <= xfer_count - 1; xfer_count <= xfer_count - 1;
else else
xfer_count_busy <= '0'; xfer_count_busy <= '0';
@@ -221,24 +303,33 @@ begin
end if; end if;
end process; end process;
PROC_SHIFT_COUNT:
process(spi_clk) process(spi_clk)
begin begin
if rising_edge(spi_clk) then if rising_edge(spi_clk) then
if data_count_en = '0' then if xfer_start_en = '1' then
word_count <= to_unsigned(0, word_count'length); shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & '1';
data_count <= cmd_reg.data_size; elsif shift_en = '1' and xfer_count_en = '1' then
data_count_busy <= '0'; if shift_cnt_pipe(shift_cnt_pipe'left) = '0' then
shift_cnt_pipe <= (others => '0'); shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & '0';
elsif shift_en = '1' then
shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & '1';
if word_count /= to_unsigned(0, word_count'length) then
word_count <= word_count - 1;
else else
word_count <= to_unsigned(word_width, word_count'length); shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & '1';
end if; end if;
if data_count /= to_unsigned(0, data_count'length) then end if;
data_count_busy <= '1'; end if;
data_count <= data_count - 1; end process;
-- Transmitter
PROC_DATA_COUNT:
process(spi_clk)
begin
if rising_edge(spi_clk) then
if xfer_start_en = '1' then
data_count <= cmd_reg.data_size;
data_count_busy <= '1';
elsif shift_en = '1' and xfer_count_en = '1' then
if data_count /= to_unsigned(2, data_count'length) then
data_count <= data_count - 1;
else else
data_count_busy <= '0'; data_count_busy <= '0';
end if; end if;
@@ -246,19 +337,37 @@ begin
end if; end if;
end process; end process;
process(spi_clk) PROC_TX_SHIFT_REG:
process(spi_clk_data)
begin begin
if rising_edge(spi_clk) then if rising_edge(spi_clk_data) then
if shift_en = '1' then if data_load_en = '1' then
if data_load_en = '0' then tx_shift_reg <= write_fifo_dout;
shift_reg <= write_fifo_dout; elsif shift_en = '1' and xfer_count_en = '1' then
elsif (ctrl.msb_first = '1') then if (ctrl_reg.msb_first = '1') then
shift_reg <= shift_reg(shift_reg'left-1 downto 0) & '0'; tx_shift_reg <= tx_shift_reg(tx_shift_reg'left-1 downto 0) & '0';
else else
shift_reg <= '0' & shift_reg(shift_reg'left downto 1); tx_shift_reg <= '0' & tx_shift_reg(tx_shift_reg'left downto 1);
end if; end if;
end if; end if;
end if; end if;
end process; end process;
-- Receiver
PROC_RX_SHIFT_REG:
process(spi_clk_out)
begin
if rising_edge(spi_clk_out) then
if shift_en = '1' and xfer_count_en = '1' then
if slv_enable = '1' then
if (ctrl_reg.msb_first = '1') then
rx_shift_reg <= rx_shift_reg(rx_shift_reg'left-1 downto 0) & miso;
else
rx_shift_reg <= miso & rx_shift_reg(rx_shift_reg'left downto 1);
end if;
end if;
end if;
end if;
end process;
end behavior; end behavior;
+12 -5
View File
@@ -7,21 +7,28 @@ use work.utils_pkg.all; -- Imports the standard textio package.
package spi_types is package spi_types is
-- Constants -- Constants
constant XFER_SIZE_MAX : natural := 256; constant XFER_MAX_SIZE_BITS : natural := 32;
-- Types -- Types
type cmd_t is record type cmd_t is record
xfer_size : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); xfer_size : unsigned(XFER_MAX_SIZE_BITS-1 downto 0);
data_size : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); data_size : unsigned(XFER_MAX_SIZE_BITS-1 downto 0);
end record; end record;
type ctrl_t is record type ctrl_t is record
polarity : std_logic; cpol : std_logic;
cpha : std_logic;
msb_first : std_logic; msb_first : std_logic;
end record; end record;
type status_t is record type status_t is record
dummy : std_logic; cmd_fifo_full : std_logic;
cmd_fifo_empty : std_logic;
write_fifo_full : std_logic;
write_fifo_empty : std_logic;
read_fifo_full : std_logic;
read_fifo_empty : std_logic;
rx_valid : std_logic;
end record; end record;
-- Functions -- Functions
+165 -29
View File
@@ -38,21 +38,33 @@ ARCHITECTURE behavior OF tb_spi IS
signal CLK : std_logic := '1'; signal CLK : std_logic := '1';
signal RST : std_logic := '1'; signal RST : std_logic := '1';
signal tx_cmd_vld : STD_LOGIC := '0'; signal mst_cmd_vld : STD_LOGIC := '0';
signal tx_cmd_rdy : STD_LOGIC; signal mst_cmd_rdy : STD_LOGIC;
signal tx_cmd : cmd_t; signal mst_cmd : cmd_t;
signal tx_din_vld : STD_LOGIC := '0'; signal mst_din_vld : STD_LOGIC := '0';
signal tx_din_rdy : STD_LOGIC; signal mst_din_rdy : STD_LOGIC;
signal tx_din : unsigned(31 downto 0) := (others => '0'); signal mst_din : unsigned(31 downto 0) := (others => '0');
signal tx_shift_en : STD_LOGIC := '1'; signal mst_dout : unsigned(31 downto 0);
signal tx_mosi : STD_LOGIC; signal mst_dout_vld : STD_LOGIC;
signal tx_clk : STD_LOGIC; signal mst_dout_re : STD_LOGIC := '1';
signal mst_shift_en : STD_LOGIC := '1';
signal mosi : STD_LOGIC;
signal miso : STD_LOGIC := '0';
signal mst_clk : STD_LOGIC;
signal ctrl : ctrl_t; signal ctrl : ctrl_t;
signal status : status_t; signal status : status_t;
signal mso : STD_LOGIC;
signal mst_rx_data : unsigned(31 downto 0);
signal slv_rx_shiftreg : unsigned(31 downto 0) := (others => '0');
signal slv_tx_shiftreg : unsigned(31 downto 0) := (others => '0');
signal slv_rx_valid_pipe : unsigned(31 downto 0) := (others => '0');
signal slv_rx_data : unsigned(31 downto 0) := (others => '0');
BEGIN BEGIN
ctrl.polarity <= '0'; ctrl.cpol <= '0';
ctrl.cpha <= '0';
ctrl.msb_first <= '1'; ctrl.msb_first <= '1';
inst_spi_tx : entity work.spi_tx inst_spi_tx : entity work.spi_tx
@@ -64,15 +76,20 @@ inst_spi_tx : entity work.spi_tx
( (
rst => RST, rst => RST,
clk => CLK, clk => CLK,
cmd_vld => tx_cmd_vld, cmd_vld => mst_cmd_vld,
cmd_rdy => tx_cmd_rdy, cmd_rdy => mst_cmd_rdy,
cmd => tx_cmd, cmd => mst_cmd,
din_vld => tx_din_vld, din_vld => mst_din_vld,
din_rdy => tx_din_rdy, din_rdy => mst_din_rdy,
din => tx_din, din => mst_din,
shift_en => tx_shift_en, dout_re => mst_dout_re,
data_out => tx_mosi, dout_vld => mst_dout_vld,
clk_out => tx_clk, dout => mst_dout,
shift_en => mst_shift_en,
mosi => mosi,
miso => miso,
sclk => mst_clk,
mso => mso,
ctrl => ctrl, ctrl => ctrl,
status => status status => status
@@ -84,6 +101,47 @@ CLK_GEN: process
CLK <= not CLK; CLK <= not CLK;
end process; end process;
RX_SLAVE_SIM_SHIFT_REG: process(mst_clk)
begin
if rising_edge(mst_clk) then
if mso = '1' then
if slv_rx_valid_pipe(slv_rx_valid_pipe'left) = '1' then
slv_rx_valid_pipe <= (slv_rx_valid_pipe'left downto 1 => '0') & '1';
else
slv_rx_valid_pipe <= slv_rx_valid_pipe(slv_rx_valid_pipe'left-1 downto 0) & '1';
end if;
slv_rx_shiftreg <= slv_rx_shiftreg(slv_rx_shiftreg'left-1 downto 0) & mosi;
slv_tx_shiftreg <= slv_tx_shiftreg(slv_tx_shiftreg'left-1 downto 0) & mosi;
else
slv_tx_shiftreg <= slv_tx_shiftreg(slv_tx_shiftreg'left-1 downto 0) & mosi;
end if;
end if;
end process;
miso <= slv_tx_shiftreg(slv_tx_shiftreg'left);
RX_SLAVE_SIM_DATA_REG: process(clk)
variable data_vld : unsigned(1 downto 0);
begin
if mso = '0' then
data_vld := "00";
elsif rising_edge(clk) then
data_vld(1) := data_vld(0);
data_vld(0) := slv_rx_valid_pipe(slv_rx_valid_pipe'left);
if data_vld(0) = '1' and data_vld(1) = '0' then
slv_rx_data <= slv_rx_shiftreg;
end if;
end if;
end process;
MASTER_TX_DATA_REG: process(clk)
begin
if rising_edge(clk) then
if mst_dout_vld = '1' then
mst_rx_data <= mst_dout;
end if;
end if;
end process;
-- Master -- Master
STIMULUS: process STIMULUS: process
@@ -95,19 +153,97 @@ STIMULUS: process
RST <= '0'; RST <= '0';
wait for 6*CLK_PERIOD; wait for 6*CLK_PERIOD;
wait for 600*CLK_PERIOD;
wait until rising_edge(CLK); wait until rising_edge(CLK);
tx_din <= X"C355AAC1"; mst_din <= X"C355AAC1";
tx_din_vld <= '1'; mst_din_vld <= '1';
wait until rising_edge(CLK) and tx_din_rdy = '1'; wait until rising_edge(CLK) and mst_din_rdy = '1';
tx_din <= X"03AAFF05"; mst_din_vld <= '0';
wait until rising_edge(CLK) and tx_din_rdy = '1';
tx_din_vld <= '0';
wait until rising_edge(CLK); wait until rising_edge(CLK);
tx_cmd <= to_cmd(64, 48); mst_cmd <= to_cmd(32, 32);
tx_cmd_vld <= '1'; mst_cmd_vld <= '1';
wait until rising_edge(CLK) and tx_cmd_rdy = '1'; wait until rising_edge(CLK) and mst_cmd_rdy = '1';
tx_cmd_vld <= '0'; mst_cmd_vld <= '0';
--------------------------------------------------------
wait until rising_edge(CLK);
mst_din <= X"C3AA55C1";
mst_din_vld <= '1';
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din_vld <= '0';
wait until rising_edge(CLK);
mst_cmd <= to_cmd(64, 64);
mst_cmd_vld <= '1';
wait until rising_edge(CLK) and mst_cmd_rdy = '1';
mst_cmd_vld <= '0';
wait for 200*CLK_PERIOD;
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din <= X"83AAFF05";
mst_din_vld <= '1';
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din_vld <= '0';
--------------------------------------------------------
wait until rising_edge(CLK);
mst_din <= X"C355AAC1";
mst_din_vld <= '1';
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din_vld <= '0';
wait until rising_edge(CLK);
mst_cmd <= to_cmd(64, 32);
mst_cmd_vld <= '1';
wait until rising_edge(CLK) and mst_cmd_rdy = '1';
mst_cmd_vld <= '0';
--------------------------------------------------------
mst_din <= X"00000000";
for i in 0 to 16 loop
wait until rising_edge(CLK);
mst_din_vld <= '1';
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din_vld <= '0';
mst_din <= mst_din + 1;
wait until rising_edge(CLK);
mst_cmd <= to_cmd(64, 32);
mst_cmd_vld <= '1';
wait until rising_edge(CLK) and mst_cmd_rdy = '1';
mst_cmd_vld <= '0';
wait until rising_edge(CLK) and mso = '1';
wait until rising_edge(CLK) and mso = '0';
end loop;
--------------------------------------------------------
wait until rising_edge(CLK);
mst_din <= X"C355AA00";
mst_din_vld <= '1';
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din_vld <= '0';
wait until rising_edge(CLK);
mst_cmd <= to_cmd(32, 24);
mst_cmd_vld <= '1';
wait until rising_edge(CLK) and mst_cmd_rdy = '1';
mst_cmd_vld <= '0';
--------------------------------------------------------
wait until rising_edge(CLK);
mst_din <= X"C355AAC1";
mst_din_vld <= '1';
wait until rising_edge(CLK) and mst_din_rdy = '1';
mst_din_vld <= '0';
wait until rising_edge(CLK);
mst_cmd <= to_cmd(24, 32);
mst_cmd_vld <= '1';
wait until rising_edge(CLK) and mst_cmd_rdy = '1';
mst_cmd_vld <= '0';
wait; wait;