- 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:
@@ -22,4 +22,4 @@ do {tb_spi.wdo}
|
|||||||
view structure
|
view structure
|
||||||
view signals
|
view signals
|
||||||
|
|
||||||
run 20 us
|
run 60 us
|
||||||
|
|||||||
+30
-20
@@ -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}
|
||||||
|
|||||||
+175
-66
@@ -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 cmd_reg_we : std_logic;
|
|
||||||
signal xfer_count_en : std_logic;
|
signal xfer_count_en : std_logic;
|
||||||
signal data_count_en : std_logic;
|
|
||||||
signal xfer_count_busy : std_logic;
|
signal xfer_count_busy : std_logic;
|
||||||
signal data_count_busy : std_logic;
|
signal data_count_busy : std_logic;
|
||||||
signal spi_clk : std_logic := '0';
|
signal spi_clk : std_logic := '0';
|
||||||
signal spi_clk_out : std_logic := '0';
|
signal spi_clk_out : std_logic;
|
||||||
signal clk_en : 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_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;
|
|
||||||
din_rdy <= not write_fifo_full;
|
|
||||||
cat_fifo_we <= cmd_vld;
|
|
||||||
cmd_reg <= to_cmd(cat_fifo_dout);
|
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);
|
mosi <= tx_shift_reg(tx_shift_reg'left) when ctrl_reg.msb_first = '1' else tx_shift_reg(tx_shift_reg'right);
|
||||||
data_load_en <= not data_count_en or shift_cnt_pipe(shift_cnt_pipe'left-1);
|
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
|
-- 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
|
||||||
|
if rst = '1' then
|
||||||
|
spi_rst <= '1';
|
||||||
|
spi_clk <= '0';
|
||||||
|
spi_rst_count <= (others => '1');
|
||||||
|
else
|
||||||
spi_clk <= not spi_clk;
|
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,48 +207,77 @@ 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 =>
|
||||||
|
read_fifo_we <= rx_enable;
|
||||||
state_next <= idle;
|
state_next <= idle;
|
||||||
|
|
||||||
when others =>
|
when others =>
|
||||||
@@ -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';
|
|
||||||
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;
|
xfer_count <= xfer_count - 1;
|
||||||
else
|
else
|
||||||
xfer_count_busy <= '0';
|
xfer_count_busy <= '0';
|
||||||
@@ -221,23 +303,32 @@ 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;
|
||||||
|
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';
|
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;
|
data_count <= data_count - 1;
|
||||||
else
|
else
|
||||||
data_count_busy <= '0';
|
data_count_busy <= '0';
|
||||||
@@ -246,16 +337,34 @@ 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 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 if;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user