- use async. FIFOs

git-svn-id: http://moon:8086/svn/vhdl/trunk@1275 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2015-06-02 19:16:16 +00:00
parent fb41f345fa
commit 7ad5c7f3c2
5 changed files with 215 additions and 35 deletions
+7
View File
@@ -5,6 +5,13 @@ if {[file exists work]} {vdel -lib work -all}
vlib work
vcom -explicit -93 "../../misc/utils_pkg.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_ctrl_pkg.vhd"
vcom -explicit -93 "../../rams/dpram_1w1r2c_ra_sim.vhd"
vcom -explicit -93 "../../FIFO/src/gray_counter.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_async_ctrl.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_async.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_sync_ctrl.vhd"
vcom -explicit -93 "../../FIFO/src/fifo_sync.vhd"
vcom -explicit -93 "../src/spi_types.vhd"
vcom -explicit -93 "../src/spi_tx.vhd"
vcom -explicit -93 "../src/spi_rx.vhd"
+17 -6
View File
@@ -3,10 +3,10 @@ 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_ack
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_re
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
@@ -16,25 +16,36 @@ 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/clk
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cmd_vld
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cmd_ack
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/cmd_rdy
add wave -noupdate -format Literal -radix hexadecimal /tb_spi/inst_spi_tx/cmd
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/din_vld
add wave -noupdate -format Logic /tb_spi/inst_spi_tx/din_re
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 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 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
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {5674147 ps} 0}
WaveRestoreCursors {{Cursor 1} {6254805 ps} 0}
configure wave -namecolwidth 197
configure wave -valuecolwidth 131
configure wave -justifyvalue left
@@ -48,4 +59,4 @@ configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
update
WaveRestoreZoom {0 ps} {21 us}
WaveRestoreZoom {5843806 ps} {8445242 ps}
+135 -19
View File
@@ -9,21 +9,25 @@ use work.spi_types.all;
ENTITY spi_tx IS
Generic
(
word_width : natural := 32
word_width : natural := 32;
CAT_FIFO_DEPTH : natural := 2;
DATA_FIFO_DEPTH : natural := 16
);
Port
(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
cmd_vld : in STD_LOGIC;
cmd_ack : out STD_LOGIC;
cmd_rdy : out STD_LOGIC;
cmd : in cmd_t;
din_vld : in STD_LOGIC;
din_re : out STD_LOGIC;
din_rdy : out STD_LOGIC;
din : in unsigned(word_width-1 downto 0);
shift_en : in STD_LOGIC;
data_out : out STD_LOGIC;
clk_out : out STD_LOGIC
clk_out : out STD_LOGIC;
ctrl : in ctrl_t;
status : out status_t
);
END spi_tx;
@@ -43,18 +47,113 @@ ARCHITECTURE behavior OF spi_tx IS
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 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 shift_cnt_pipe : unsigned(word_width-1 downto 0);
signal data_load_en : std_logic;
--------------------------------------------------------------------------
begin
clk_out <= clk and clk_en;
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);
--------------------------------------------------------------------------
proc_state_next:
-- Instantiate synchronous FIFO
inst_cat_fifo: entity work.fifo_async
GENERIC MAP
(
addr_width => NextExpBaseTwo(CAT_FIFO_DEPTH),
data_width => cmd_size
)
PORT MAP
(
rst => rst,
clk_w => clk,
clk_r => spi_clk,
we => cat_fifo_we,
re => cat_fifo_re,
fifo_full => cat_fifo_full,
fifo_empty => cat_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => cat_fifo_din,
data_r => cat_fifo_dout
);
-- Instantiate synchronous FIFO
inst_write_fifo: entity work.fifo_async
GENERIC MAP
(
addr_width => NextExpBaseTwo(DATA_FIFO_DEPTH),
data_width => word_width
)
PORT MAP
(
rst => rst,
clk_w => clk,
clk_r => spi_clk,
we => din_vld,
re => write_fifo_re,
fifo_full => write_fifo_full,
fifo_empty => write_fifo_empty,
fifo_afull => open,
fifo_aempty => open,
data_w => write_fifo_din,
data_r => write_fifo_dout
);
--------------------------------------------------------------------------
proc_spi_clk_gen:
process(clk)
begin
if rising_edge(clk) then
spi_clk <= not spi_clk;
end if;
end process;
proc_spi_clk_out_gen:
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
spi_clk_out <= '0';
elsif clk_en = '0' then
spi_clk_out <= ctrl.polarity;
else
spi_clk_out <= not spi_clk_out;
end if;
end if;
end process;
proc_state_next:
process(spi_clk)
begin
if rising_edge(spi_clk) then
if rst = '1' then
state <= idle;
else
@@ -64,24 +163,26 @@ begin
end process;
proc_fsm:
process(state, cmd_vld, xfer_count_busy)
process(state, cat_fifo_empty, xfer_count_busy)
begin
state_next <= state;
cmd_reg_we <= '0';
cmd_ack <= '0';
cat_fifo_re <= '0';
xfer_count_en <= '0';
data_count_en <= '0';
clk_en <= '0';
case state is
when idle =>
cmd_ack <= cmd_vld;
if cmd_vld = '1' then
if cat_fifo_empty = '0' then
cmd_reg_we <= '1';
state_next <= prepare;
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;
@@ -103,11 +204,11 @@ begin
end case;
end process;
process(clk)
process(spi_clk)
begin
if rising_edge(clk) then
if rising_edge(spi_clk) then
if xfer_count_en = '0' then
xfer_count <= cmd.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
@@ -120,22 +221,22 @@ begin
end if;
end process;
process(clk)
process(spi_clk)
begin
if rising_edge(clk) then
din_re <= '0';
if rising_edge(spi_clk) then
if data_count_en = '0' then
word_count <= to_unsigned(0, word_count'length);
data_count <= cmd.data_size;
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;
else
din_re <= '1';
word_count <= to_unsigned(word_width, word_count'length);
end if;
if data_count /= to_unsigned(1, data_count'length) then
if data_count /= to_unsigned(0, data_count'length) then
data_count_busy <= '1';
data_count <= data_count - 1;
else
@@ -145,4 +246,19 @@ begin
end if;
end process;
process(spi_clk)
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';
else
shift_reg <= '0' & shift_reg(shift_reg'left downto 1);
end if;
end if;
end if;
end process;
end behavior;
+34 -4
View File
@@ -13,26 +13,56 @@ package spi_types is
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);
end record;
type ctrl_t is record
polarity : std_logic;
msb_first : std_logic;
end record;
type status_t is record
dummy : std_logic;
end record;
-- Functions
function cmd_size return positive;
function to_cmd (xfer_size, data_size : natural) return cmd_t;
function to_unsigned (cmd : cmd_t) return unsigned;
function to_cmd (cmd : unsigned) return cmd_t;
end spi_types;
package body spi_types is
function cmd_size return positive is
variable res : cmd_t;
begin
return res.xfer_size'length + res.data_size'length + 1 + 1;
end cmd_size;
function to_cmd(xfer_size, data_size : natural) return cmd_t is
variable res : cmd_t;
begin
res.polarity := '1';
res.msb_first := '1';
res.xfer_size := to_unsigned(xfer_size, res.xfer_size'length);
res.data_size := to_unsigned(data_size, res.data_size'length);
return res;
end to_cmd;
function to_unsigned(cmd : cmd_t) return unsigned is
variable res : unsigned(cmd.xfer_size'length + cmd.data_size'length + 1 + 1 -1 downto 0) := (others => '0');
begin
res(res'left downto res'left - cmd.xfer_size'length+1) := cmd.xfer_size;
res(res'left - cmd.xfer_size'length downto res'left - cmd.xfer_size'length - cmd.data_size'length +1) := cmd.data_size;
return res;
end to_unsigned;
function to_cmd (cmd : unsigned) return cmd_t is
variable res : cmd_t;
begin
res.xfer_size := cmd(cmd'left downto cmd'left - res.xfer_size'length+1);
res.data_size := cmd(cmd'left - res.xfer_size'length downto cmd'left - res.xfer_size'length - res.data_size'length +1);
return res;
end to_cmd;
end spi_types;
+22 -6
View File
@@ -39,17 +39,22 @@ ARCHITECTURE behavior OF tb_spi IS
signal RST : std_logic := '1';
signal tx_cmd_vld : STD_LOGIC := '0';
signal tx_cmd_ack : STD_LOGIC;
signal tx_cmd_rdy : STD_LOGIC;
signal tx_cmd : cmd_t;
signal tx_din_vld : STD_LOGIC := '0';
signal tx_din_re : STD_LOGIC;
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 ctrl : ctrl_t;
signal status : status_t;
BEGIN
ctrl.polarity <= '0';
ctrl.msb_first <= '1';
inst_spi_tx : entity work.spi_tx
GENERIC MAP
(
@@ -60,14 +65,16 @@ inst_spi_tx : entity work.spi_tx
rst => RST,
clk => CLK,
cmd_vld => tx_cmd_vld,
cmd_ack => tx_cmd_ack,
cmd_rdy => tx_cmd_rdy,
cmd => tx_cmd,
din_vld => tx_din_vld,
din_re => tx_din_re,
din_rdy => tx_din_rdy,
din => tx_din,
shift_en => tx_shift_en,
data_out => tx_mosi,
clk_out => tx_clk
clk_out => tx_clk,
ctrl => ctrl,
status => status
);
@@ -86,11 +93,20 @@ STIMULUS: process
wait for 600*CLK_PERIOD;
RST <= '0';
wait for 6*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';
wait until rising_edge(CLK);
tx_cmd <= to_cmd(64, 48);
tx_cmd_vld <= '1';
wait until rising_edge(CLK) and tx_cmd_ack = '1';
wait until rising_edge(CLK) and tx_cmd_rdy = '1';
tx_cmd_vld <= '0';
wait;