From 6605ecc2ac79d53ef1c78827ba29ad83f9afd2c9 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Thu, 4 Jun 2015 11:09:56 +0000 Subject: [PATCH] - Master RX and TX working git-svn-id: http://moon:8086/svn/vhdl/trunk@1276 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/spi/sim/tb_spi.fdo | 2 +- lib/spi/sim/tb_spi.wdo | 50 ++++--- lib/spi/src/spi_tx.vhd | 285 ++++++++++++++++++++++++++------------ lib/spi/src/spi_types.vhd | 17 ++- lib/spi/src/tb_spi.vhd | 194 ++++++++++++++++++++++---- 5 files changed, 405 insertions(+), 143 deletions(-) diff --git a/lib/spi/sim/tb_spi.fdo b/lib/spi/sim/tb_spi.fdo index 096886a..82afc7b 100644 --- a/lib/spi/sim/tb_spi.fdo +++ b/lib/spi/sim/tb_spi.fdo @@ -22,4 +22,4 @@ do {tb_spi.wdo} view structure view signals -run 20 us +run 60 us diff --git a/lib/spi/sim/tb_spi.wdo b/lib/spi/sim/tb_spi.wdo index 2c74d36..9b1a916 100644 --- a/lib/spi/sim/tb_spi.wdo +++ b/lib/spi/sim/tb_spi.wdo @@ -2,15 +2,26 @@ onerror {resume} quietly WaveActivateNextPane {} 0 add wave -noupdate -format Logic /tb_spi/clk 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/tx_cmd_rdy -add wave -noupdate -format Literal -radix hexadecimal /tb_spi/tx_cmd -add wave -noupdate -format Logic /tb_spi/tx_din_vld -add wave -noupdate -format Logic /tb_spi/tx_din_rdy -add wave -noupdate -format Literal -radix hexadecimal /tb_spi/tx_din -add wave -noupdate -format Logic /tb_spi/tx_shift_en -add wave -noupdate -format Logic /tb_spi/tx_mosi -add wave -noupdate -format Logic /tb_spi/tx_clk +add wave -noupdate -format Logic /tb_spi/mst_cmd_vld +add wave -noupdate -format Logic /tb_spi/mst_cmd_rdy +add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_cmd +add wave -noupdate -format Logic /tb_spi/mst_din_vld +add wave -noupdate -format Logic /tb_spi/mst_din_rdy +add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_din +add wave -noupdate -format Logic /tb_spi/mst_shift_en +add wave -noupdate -format Literal -radix hexadecimal /tb_spi/mst_dout +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 -format Literal /tb_spi/inst_spi_tx/word_width 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 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/data_out -add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_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/mosi +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/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/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 /tb_spi/inst_spi_tx/state 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 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/data_count_en 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/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_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_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] -WaveRestoreCursors {{Cursor 1} {6254805 ps} 0} +WaveRestoreCursors {{Cursor 1} {17474865 ps} 0} configure wave -namecolwidth 197 configure wave -valuecolwidth 131 configure wave -justifyvalue left @@ -59,4 +69,4 @@ configure wave -gridperiod 1 configure wave -griddelta 40 configure wave -timeline 0 update -WaveRestoreZoom {5843806 ps} {8445242 ps} +WaveRestoreZoom {0 ps} {63 us} diff --git a/lib/spi/src/spi_tx.vhd b/lib/spi/src/spi_tx.vhd index 11c3951..2eb9bc5 100644 --- a/lib/spi/src/spi_tx.vhd +++ b/lib/spi/src/spi_tx.vhd @@ -23,64 +23,84 @@ ENTITY spi_tx IS din_vld : in STD_LOGIC; din_rdy : out STD_LOGIC; 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; - data_out : out STD_LOGIC; - clk_out : out STD_LOGIC; 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; 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 data_count : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); - signal word_count : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); - signal cmd_reg : cmd_t; - signal state : state_t; - signal state_next : state_t; - signal cmd_reg_we : std_logic; - signal xfer_count_en : std_logic; - signal data_count_en : std_logic; - signal xfer_count_busy : std_logic; - signal data_count_busy : std_logic; - signal spi_clk : std_logic := '0'; - signal spi_clk_out : std_logic := '0'; - signal clk_en : std_logic; + signal xfer_count : unsigned(XFER_MAX_SIZE_BITS-1 downto 0); + signal data_count : unsigned(XFER_MAX_SIZE_BITS-1 downto 0); + signal cmd_reg : cmd_t; + signal state : state_t; + signal state_next : state_t; + signal xfer_count_en : std_logic; + signal xfer_count_busy : std_logic; + signal data_count_busy : std_logic; + signal spi_clk : std_logic := '0'; + signal spi_clk_out : std_logic; + signal clk_en : std_logic; + signal spi_clk_data : std_logic; + signal spi_rst_count : unsigned(5 downto 0); + signal spi_rst : std_logic; 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_re : std_logic; - signal cat_fifo_we : std_logic; signal cat_fifo_full : std_logic; signal cat_fifo_empty : std_logic; signal write_fifo_din : 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_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 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 - clk_out <= spi_clk_out; - cat_fifo_din <= to_unsigned(cmd); - write_fifo_din <= din; - cmd_rdy <= not cat_fifo_full; - din_rdy <= not write_fifo_full; - cat_fifo_we <= cmd_vld; - 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); - data_load_en <= not data_count_en or shift_cnt_pipe(shift_cnt_pipe'left-1); + sclk <= spi_clk_out; + cat_fifo_din <= to_unsigned(cmd); + write_fifo_din <= din; + cmd_reg <= to_cmd(cat_fifo_dout); + mosi <= tx_shift_reg(tx_shift_reg'left) when ctrl_reg.msb_first = '1' else tx_shift_reg(tx_shift_reg'right); + spi_clk_data <= spi_clk xor ctrl_reg.cpha; + + dout_vld <= not read_fifo_empty; + 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 @@ -92,11 +112,11 @@ begin ) PORT MAP ( - rst => rst, + rst => spi_rst, clk_w => clk, clk_r => spi_clk, - we => cat_fifo_we, - re => cat_fifo_re, + we => cmd_vld, + re => xfer_start_en, fifo_full => cat_fifo_full, fifo_empty => cat_fifo_empty, fifo_afull => open, @@ -114,11 +134,11 @@ begin ) PORT MAP ( - rst => rst, + rst => spi_rst, clk_w => clk, clk_r => spi_clk, we => din_vld, - re => write_fifo_re, + re => data_load_en, fifo_full => write_fifo_full, fifo_empty => write_fifo_empty, fifo_afull => open, @@ -127,12 +147,45 @@ begin 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: process(clk) begin 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 process; @@ -140,10 +193,10 @@ proc_spi_clk_out_gen: process(clk) begin if rising_edge(clk) then - if rst = '1' then + if spi_rst = '1' then spi_clk_out <= '0'; elsif clk_en = '0' then - spi_clk_out <= ctrl.polarity; + spi_clk_out <= ctrl_reg.cpol; else spi_clk_out <= not spi_clk_out; end if; @@ -154,65 +207,94 @@ proc_state_next: process(spi_clk) begin if rising_edge(spi_clk) then - if rst = '1' then - state <= idle; + if spi_rst = '1' then + state <= reset; else state <= state_next; end if; end if; 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: -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 state_next <= state; - cmd_reg_we <= '0'; - cat_fifo_re <= '0'; - xfer_count_en <= '0'; - data_count_en <= '0'; - clk_en <= '0'; + + xfer_start_en <= '0'; + xfer_count_en <= '0'; + data_load_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 + + when reset => + cmd_rdy <= '0'; + din_rdy <= '0'; + slv_enable <= '0'; + state_next <= idle; when idle => + slv_enable <= '0'; if cat_fifo_empty = '0' then - cmd_reg_we <= '1'; - state_next <= prepare; + state_next <= load_data; + xfer_start_en <= '1'; end if; - when prepare => - cat_fifo_re <= '1'; - write_fifo_re <= '1'; - clk_en <= '1'; - xfer_count_en <= '1'; - data_count_en <= '1'; - state_next <= shift; + when load_data => + if xfer_count_busy = '0' then + state_next <= idle; + elsif write_fifo_empty = '0' then + data_load_en <= '1'; + state_next <= shift; + clk_en <= ctrl_reg.cpha; + end if; when shift => - clk_en <= '1'; - xfer_count_en <= '1'; - data_count_en <= '1'; + clk_en <= '1'; + xfer_count_en <= '1'; if xfer_count_busy = '0' then 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; when finish => - state_next <= idle; - + read_fifo_we <= rx_enable; + state_next <= idle; + when others => state_next <= idle; end case; end process; +PROC_XFER_COUNT: process(spi_clk) begin 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_busy <= '0'; - elsif shift_en = '1' then - if xfer_count /= to_unsigned(0, xfer_count'length) then - xfer_count_busy <= '1'; + xfer_count_busy <= '1'; + elsif shift_en = '1' and xfer_count_en = '1' then + if xfer_count /= to_unsigned(2, xfer_count'length) then xfer_count <= xfer_count - 1; else xfer_count_busy <= '0'; @@ -221,24 +303,33 @@ begin end if; end process; +PROC_SHIFT_COUNT: process(spi_clk) begin if rising_edge(spi_clk) then - if data_count_en = '0' then - word_count <= to_unsigned(0, word_count'length); - data_count <= cmd_reg.data_size; - data_count_busy <= '0'; - shift_cnt_pipe <= (others => '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; + if xfer_start_en = '1' then + shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & '1'; + elsif shift_en = '1' and xfer_count_en = '1' then + if shift_cnt_pipe(shift_cnt_pipe'left) = '0' then + shift_cnt_pipe <= shift_cnt_pipe(shift_cnt_pipe'left-1 downto 0) & '0'; else - word_count <= to_unsigned(word_width, word_count'length); + shift_cnt_pipe <= (shift_cnt_pipe'left downto 1 => '0') & '1'; end if; - if data_count /= to_unsigned(0, data_count'length) then - data_count_busy <= '1'; - data_count <= data_count - 1; + end if; + end if; +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 data_count_busy <= '0'; end if; @@ -246,19 +337,37 @@ begin end if; end process; -process(spi_clk) +PROC_TX_SHIFT_REG: +process(spi_clk_data) begin - if rising_edge(spi_clk) then - if shift_en = '1' then - if data_load_en = '0' then - shift_reg <= write_fifo_dout; - elsif (ctrl.msb_first = '1') then - shift_reg <= shift_reg(shift_reg'left-1 downto 0) & '0'; + if rising_edge(spi_clk_data) then + if data_load_en = '1' then + tx_shift_reg <= write_fifo_dout; + elsif shift_en = '1' and xfer_count_en = '1' then + if (ctrl_reg.msb_first = '1') then + tx_shift_reg <= tx_shift_reg(tx_shift_reg'left-1 downto 0) & '0'; 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 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; diff --git a/lib/spi/src/spi_types.vhd b/lib/spi/src/spi_types.vhd index 436a201..cbfae48 100644 --- a/lib/spi/src/spi_types.vhd +++ b/lib/spi/src/spi_types.vhd @@ -7,21 +7,28 @@ use work.utils_pkg.all; -- Imports the standard textio package. package spi_types is -- Constants - constant XFER_SIZE_MAX : natural := 256; + constant XFER_MAX_SIZE_BITS : natural := 32; -- Types type cmd_t is record - xfer_size : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); - data_size : unsigned(NextExpBaseTwo(XFER_SIZE_MAX)-1 downto 0); + xfer_size : unsigned(XFER_MAX_SIZE_BITS-1 downto 0); + data_size : unsigned(XFER_MAX_SIZE_BITS-1 downto 0); end record; type ctrl_t is record - polarity : std_logic; + cpol : std_logic; + cpha : std_logic; msb_first : std_logic; end 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; -- Functions diff --git a/lib/spi/src/tb_spi.vhd b/lib/spi/src/tb_spi.vhd index 949b9d8..0663fbb 100644 --- a/lib/spi/src/tb_spi.vhd +++ b/lib/spi/src/tb_spi.vhd @@ -38,21 +38,33 @@ ARCHITECTURE behavior OF tb_spi IS signal CLK : std_logic := '1'; signal RST : std_logic := '1'; - signal tx_cmd_vld : STD_LOGIC := '0'; - signal tx_cmd_rdy : STD_LOGIC; - signal tx_cmd : cmd_t; - signal tx_din_vld : STD_LOGIC := '0'; - signal tx_din_rdy : STD_LOGIC; - signal tx_din : unsigned(31 downto 0) := (others => '0'); - signal tx_shift_en : STD_LOGIC := '1'; - signal tx_mosi : STD_LOGIC; - signal tx_clk : STD_LOGIC; + signal mst_cmd_vld : STD_LOGIC := '0'; + signal mst_cmd_rdy : STD_LOGIC; + signal mst_cmd : cmd_t; + signal mst_din_vld : STD_LOGIC := '0'; + signal mst_din_rdy : STD_LOGIC; + signal mst_din : unsigned(31 downto 0) := (others => '0'); + signal mst_dout : unsigned(31 downto 0); + signal mst_dout_vld : 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 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 - ctrl.polarity <= '0'; + ctrl.cpol <= '0'; + ctrl.cpha <= '0'; ctrl.msb_first <= '1'; inst_spi_tx : entity work.spi_tx @@ -64,15 +76,20 @@ inst_spi_tx : entity work.spi_tx ( rst => RST, clk => CLK, - cmd_vld => tx_cmd_vld, - cmd_rdy => tx_cmd_rdy, - cmd => tx_cmd, - din_vld => tx_din_vld, - din_rdy => tx_din_rdy, - din => tx_din, - shift_en => tx_shift_en, - data_out => tx_mosi, - clk_out => tx_clk, + cmd_vld => mst_cmd_vld, + cmd_rdy => mst_cmd_rdy, + cmd => mst_cmd, + din_vld => mst_din_vld, + din_rdy => mst_din_rdy, + din => mst_din, + dout_re => mst_dout_re, + dout_vld => mst_dout_vld, + dout => mst_dout, + shift_en => mst_shift_en, + mosi => mosi, + miso => miso, + sclk => mst_clk, + mso => mso, ctrl => ctrl, status => status @@ -84,6 +101,47 @@ CLK_GEN: process CLK <= not CLK; 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 STIMULUS: process @@ -95,20 +153,98 @@ STIMULUS: process RST <= '0'; wait for 6*CLK_PERIOD; + wait for 600*CLK_PERIOD; wait until rising_edge(CLK); - tx_din <= X"C355AAC1"; - tx_din_vld <= '1'; - wait until rising_edge(CLK) and tx_din_rdy = '1'; - tx_din <= X"03AAFF05"; - wait until rising_edge(CLK) and tx_din_rdy = '1'; - tx_din_vld <= '0'; + 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); - tx_cmd <= to_cmd(64, 48); - tx_cmd_vld <= '1'; - wait until rising_edge(CLK) and tx_cmd_rdy = '1'; - tx_cmd_vld <= '0'; + mst_cmd <= to_cmd(32, 32); + 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"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; end process;