From 285ebe2795fbffcc8a74f5b697ede54545209022 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Mon, 27 May 2013 11:16:41 +0000 Subject: [PATCH] Initial revision Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@971 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/JBUS/sim/tb_dma.fdo | 21 ++ lib/JBUS/sim/tb_dma.wdo | 173 ++++++++++ lib/JBUS/src/busmaster_types.vhd | 33 ++ lib/JBUS/src/dma.vhd | 232 +++++++++++++ lib/JBUS/src/tb_dma.vhd | 552 +++++++++++++++++++++++++++++++ 5 files changed, 1011 insertions(+) create mode 100644 lib/JBUS/sim/tb_dma.fdo create mode 100644 lib/JBUS/sim/tb_dma.wdo create mode 100644 lib/JBUS/src/busmaster_types.vhd create mode 100644 lib/JBUS/src/dma.vhd create mode 100644 lib/JBUS/src/tb_dma.vhd diff --git a/lib/JBUS/sim/tb_dma.fdo b/lib/JBUS/sim/tb_dma.fdo new file mode 100644 index 0000000..5f85f2a --- /dev/null +++ b/lib/JBUS/sim/tb_dma.fdo @@ -0,0 +1,21 @@ +## NOTE: Do not edit this file. +## Autogenerated by ProjNav (creatfdo.tcl) on Thu Jul 06 20:49:07 Westeuropäische Sommerzeit 2006 +## +vlib work +vcom -explicit -93 "../../misc/utils_pkg.vhd" +vcom -explicit -93 "../../rams/dpram_1w1r2c_ra_sim.vhd" +vcom -explicit -93 "../../rams/dpram_1w1r2c_ro_sim.vhd" +vcom -explicit -93 "../../FIFO/src/fifo_ctrl_pkg.vhd" +vcom -explicit -93 "../../FIFO/src/fifo_sync_ctrl.vhd" +vcom -explicit -93 "../../FIFO/src/fifo_sync.vhd" +vcom -explicit -93 "../src/busmaster_types.vhd" +vcom -explicit -93 "../src/busmaster_sync.vhd" +vcom -explicit -93 "../src/dma.vhd" +vcom -explicit -93 "../src/tb_dma.vhd" +vsim -t 1ps -lib work tb_dma +view wave +do {tb_dma.wdo} +view structure +view signals + +run 20us diff --git a/lib/JBUS/sim/tb_dma.wdo b/lib/JBUS/sim/tb_dma.wdo new file mode 100644 index 0000000..49b558a --- /dev/null +++ b/lib/JBUS/sim/tb_dma.wdo @@ -0,0 +1,173 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/read_reg +add wave -noupdate -format Literal /tb_dma/dma_master_req +add wave -noupdate -format Literal /tb_dma/dma_master_gnt +add wave -noupdate -format Literal /tb_dma/dma_req_rdy +add wave -noupdate -format Literal /tb_dma/dma_req_en +add wave -noupdate -format Literal /tb_dma/dma_req_rw +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/dma_req_addr +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/dma_req_addr_inc +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/dma_req_num_xfers +add wave -noupdate -format Literal /tb_dma/dma_req_complete +add wave -noupdate -format Literal /tb_dma/dma_req_complete_ack +add wave -noupdate -format Logic /tb_dma/bus_cmd_cycle_finished +add wave -noupdate -format Logic /tb_dma/bus_cmd_cycle_en +add wave -noupdate -format Logic /tb_dma/bus_cmd_rdy +add wave -noupdate -format Logic /tb_dma/bus_cmd_we +add wave -noupdate -format Literal -radix hexadecimal -expand /tb_dma/bus_cmd +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/bus_dout +add wave -noupdate -format Logic /tb_dma/bus_dout_vld +add wave -noupdate -format Logic /tb_dma/bus_dout_re +add wave -noupdate -format Logic /tb_dma/bus_din_rdy +add wave -noupdate -format Logic /tb_dma/bus_din_vld +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/bus_din +add wave -noupdate -divider Busmaster +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_we +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/cmd_in +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/din +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/din_rdy +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/din_we +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/dout +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/dout_vld +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/dout_re +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/ack_i +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/srdy_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/mdat_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/mdat_o +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/addr_o +add wave -noupdate -format Literal /tb_dma/inst_busmaster_sync/sel_o +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/we_o +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cyc_o +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/stb_o +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/mrdy_o +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/cmd_fifo_din +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/inst_busmaster_sync/cmd_fifo_dout +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_fifo_re +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_fifo_we +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_fifo_full +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_fifo_empty +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/read_fifo_re +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/read_fifo_we +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/read_fifo_full +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/read_fifo_empty +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/write_fifo_re +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/write_fifo_we +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/write_fifo_full +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/write_fifo_empty +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cycle_busy +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_en +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/cmd_read_en +add wave -noupdate -format Literal /tb_dma/inst_busmaster_sync/read_cnt +add wave -noupdate -format Logic /tb_dma/inst_busmaster_sync/write +add wave -noupdate -divider JBUS +add wave -noupdate -format Logic /tb_dma/clk_o +add wave -noupdate -format Logic /tb_dma/rst_o +add wave -noupdate -format Logic /tb_dma/int_o +add wave -noupdate -format Logic /tb_dma/cyc_o +add wave -noupdate -format Logic /tb_dma/stb_o +add wave -noupdate -format Logic /tb_dma/we_o +add wave -noupdate -format Literal /tb_dma/sel_o +add wave -noupdate -format Logic /tb_dma/ack_i +add wave -noupdate -format Logic /tb_dma/mrdy_o +add wave -noupdate -format Logic /tb_dma/srdy_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/addr_o +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/mdat_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/mdat_o +add wave -noupdate -divider {DMA 0} +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/clk +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/rst +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/master_req +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/master_gnt +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_rdy +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_rw +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/req_addr +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/req_addr_inc +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/req_num_xfers +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_complete +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_complete_ack +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/bus_cyc_complete +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/bus_cmd_rdy +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/bus_cmd_we +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/bus_cmd_cycle_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/bus_cmd_out +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/start_en +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/finish_en +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/complete +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/rw +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/addr +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/addr_incr +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/req_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/req_count_next +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/req_count_rdy +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/chunk_count_rst +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/chunk_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/chunk_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__0/inst_uut/chunk_count_next +add wave -noupdate -format Logic /tb_dma/gen_uut__0/inst_uut/chunk_count_rdy +add wave -noupdate -format Literal /tb_dma/gen_uut__0/inst_uut/s +add wave -noupdate -divider {DMA 1} +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/clk +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/rst +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/master_req +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/master_gnt +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_rdy +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_rw +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/req_addr +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/req_addr_inc +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/req_num_xfers +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_complete +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_complete_ack +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/bus_cyc_complete +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/bus_cmd_rdy +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/bus_cmd_we +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/bus_cmd_cycle_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/bus_cmd_out +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/start_en +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/finish_en +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/complete +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/rw +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/addr +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/addr_incr +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/req_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/req_count_next +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/req_count_rdy +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/chunk_count_rst +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/chunk_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/chunk_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/gen_uut__1/inst_uut/chunk_count_next +add wave -noupdate -format Logic /tb_dma/gen_uut__1/inst_uut/chunk_count_rdy +add wave -noupdate -format Literal /tb_dma/gen_uut__1/inst_uut/s +add wave -noupdate -divider {Read FIFO} +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/data_gen_reg +add wave -noupdate -format Logic /tb_dma/data_gen_reg_inc +add wave -noupdate -format Literal /tb_dma/dma_write_source +add wave -noupdate -format Logic /tb_dma/read_fifo_re +add wave -noupdate -format Logic /tb_dma/read_fifo_we +add wave -noupdate -format Logic /tb_dma/read_fifo_full +add wave -noupdate -format Logic /tb_dma/read_fifo_empty +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/read_fifo_din +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/read_fifo_dout +add wave -noupdate -divider RAM +add wave -noupdate -format Literal /tb_dma/state +add wave -noupdate -format Literal -radix hexadecimal /tb_dma/ram64 +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {2164007 ps} 0} +configure wave -namecolwidth 150 +configure wave -valuecolwidth 100 +configure wave -justifyvalue left +configure wave -signalnamewidth 1 +configure wave -snapdistance 10 +configure wave -datasetprefix 0 +configure wave -rowmargin 4 +configure wave -childrowmargin 2 +configure wave -gridoffset 0 +configure wave -gridperiod 1 +configure wave -griddelta 40 +configure wave -timeline 0 +update +WaveRestoreZoom {2024163 ps} {2253131 ps} diff --git a/lib/JBUS/src/busmaster_types.vhd b/lib/JBUS/src/busmaster_types.vhd new file mode 100644 index 0000000..e25b9fd --- /dev/null +++ b/lib/JBUS/src/busmaster_types.vhd @@ -0,0 +1,33 @@ +-- Package File Template +-- +-- Purpose: This package defines supplemental types, subtypes, +-- constants, and functions + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use IEEE.MATH_REAL.ALL; + +package busmaster_types is + + -- Constants + + -- Types + + type bm_cmd_t is + record + addr : unsigned(31 downto 0); + sel : unsigned(3 downto 0); + rw : std_logic; + end record; + +end busmaster_types; + + +package body busmaster_types is + + +end busmaster_types; + + diff --git a/lib/JBUS/src/dma.vhd b/lib/JBUS/src/dma.vhd new file mode 100644 index 0000000..1047d84 --- /dev/null +++ b/lib/JBUS/src/dma.vhd @@ -0,0 +1,232 @@ +----------------------------------------------------------------------- +-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/dma.vhd,v 1.1 2013-05-27 11:15:58 jens Exp $ +----------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +use work.utils_pkg.all; +use work.busmaster_types.all; + +------------------------------------------------------------------ +entity dma is + Generic + ( + DATA_WIDTH : natural := 32; + XFER_CHUNK_SIZE : natural := 512 + ); + Port + ( + clk : in std_logic; + rst : in std_logic; + + master_req : out std_logic; + master_gnt : in std_logic; + + req_rdy : out std_logic; + req_rw : in std_logic; + req_en : in std_logic; + req_addr : in unsigned(31 downto 0); + req_addr_inc : in unsigned(31 downto 0); + req_num_xfers : in unsigned(31 downto 0); + + req_complete : out std_logic; + req_complete_ack : in std_logic; + + -- busmaster control + bus_source_en : out std_logic; + bus_cyc_complete : in std_logic; + bus_cmd_rdy : in std_logic; + bus_cmd_we : out std_logic; + bus_cmd_cycle_en : out std_logic; + + -- busmaster command + bus_cmd_out : out bm_cmd_t + ); + end dma; + +architecture Behavioral of dma is + + signal start_en : std_logic; + signal finish_en : std_logic; + signal complete : std_logic; + signal rw : std_logic; + signal addr : unsigned(31 downto 0); + signal addr_incr : unsigned(31 downto 0); + + signal req_count_en : std_logic; + signal req_count : unsigned(31 downto 0); + signal req_count_next : unsigned(32 downto 0); + signal req_count_rdy : std_logic; + + signal chunk_count_rst : std_logic; + signal chunk_count_en : std_logic; + signal chunk_count : unsigned(31 downto 0); + signal chunk_count_next : unsigned(32 downto 0); + signal chunk_count_rdy : std_logic; + + type state_t is (INIT, READY, SETUP, XFER_WRITE, XFER_READ, FINISH); + signal s, sn : state_t; + +begin + + bus_cmd_out.addr <= addr; + bus_cmd_out.sel <= "1111"; + bus_cmd_out.rw <= rw; + req_complete <= complete; + +state_next: + process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + s <= INIT; + else + s <= sn; + end if; + end if; + end process; + +state: + process(s, req_en, rw, master_gnt, req_count_rdy, chunk_count_rdy, bus_cyc_complete, bus_cmd_rdy) + begin + + bus_cmd_cycle_en <= '0'; + bus_cmd_we <= '0'; + start_en <= '0'; + finish_en <= '0'; + req_count_en <= '0'; + req_rdy <= '0'; + chunk_count_rst <= '0'; + chunk_count_en <= '0'; + master_req <= '0'; + bus_source_en <= '0'; + + sn <= s; + case s is + when INIT => + sn <= READY; + + when READY => + req_rdy <= '1'; + if req_en = '1' then + start_en <= '1'; + sn <= SETUP; + end if; + + when SETUP => + master_req <= '1'; + chunk_count_rst <= '1'; + if req_count_rdy = '1' then + sn <= READY; + elsif master_gnt = '1' and bus_cyc_complete = '1' then + if rw = '1' then + sn <= XFER_WRITE; + else + sn <= XFER_READ; + end if; + end if; + + when XFER_WRITE => + master_req <= '1'; + bus_cmd_we <= '1'; + bus_cmd_cycle_en <= '1'; + req_count_en <= bus_cmd_rdy; + chunk_count_en <= bus_cmd_rdy; + bus_source_en <= '1'; + if req_count_rdy = '1' then + sn <= FINISH; + elsif chunk_count_rdy = '1' then + sn <= SETUP; + end if; + + when XFER_READ => + master_req <= '1'; + bus_cmd_we <= '1'; + bus_cmd_cycle_en <= '1'; + req_count_en <= bus_cmd_rdy; + chunk_count_en <= bus_cmd_rdy; + if req_count_rdy = '1' then + sn <= FINISH; + elsif chunk_count_rdy = '1' then + sn <= SETUP; + end if; + + when FINISH => + master_req <= '1'; + if bus_cyc_complete = '1' then + sn <= READY; + finish_en <= '1'; + end if; + + when others => + sn <= READY; + + end case; + end process; + +addr_gen: + process(clk) + begin + if rising_edge(clk) then + if start_en = '1' then + addr <= req_addr; + addr_incr <= req_addr_inc; + rw <= req_rw; + elsif req_count_en = '1' then + addr <= addr + addr_incr; + end if; + end if; + end process; + + req_count_next <= ('0' & req_num_xfers) - 1 when start_en = '1' else ('0' & req_count) - 1; + req_count_rdy <= req_count_next(32); + +req_counter: + process(clk) + begin + if rising_edge(clk) then + if start_en = '1' then + req_count <= req_count_next(31 downto 0); + elsif req_count_en = '1' then + if req_count_rdy = '0' then + req_count <= req_count_next(31 downto 0); + end if; + end if; + end if; + end process; + + chunk_count_next <= to_unsigned(XFER_CHUNK_SIZE, 33) - 1 when chunk_count_rst = '1' else ('0' & chunk_count) - 1; + chunk_count_rdy <= chunk_count_next(32); + +chunk_counter: + process(clk) + begin + if rising_edge(clk) then + if chunk_count_rst = '1' then + chunk_count <= chunk_count_next(31 downto 0); + elsif chunk_count_en = '1' then + if chunk_count_rdy = '0' then + chunk_count <= chunk_count_next(31 downto 0); + end if; + end if; + end if; + end process; + +complete_register: + process(clk) + begin + if rising_edge(clk) then + if start_en = '1' or rst = '1' then + complete <= '0'; + elsif complete = '0' then + if finish_en = '1' then + complete <= '1'; + elsif req_complete_ack = '1' then + complete <= '0'; + end if; + end if; + end if; + end process; + +end Behavioral; diff --git a/lib/JBUS/src/tb_dma.vhd b/lib/JBUS/src/tb_dma.vhd new file mode 100644 index 0000000..e22676d --- /dev/null +++ b/lib/JBUS/src/tb_dma.vhd @@ -0,0 +1,552 @@ +----------------------------------------------------------------------- +-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/tb_dma.vhd,v 1.1 2013-05-27 11:15:58 jens Exp $ +----------------------------------------------------------------------- + +LIBRARY ieee; +use IEEE.STD_LOGIC_1164.ALL; +USE ieee.numeric_std.ALL; + +use work.busmaster_types.all; + +ENTITY tb_dma IS +END tb_dma; + +ARCHITECTURE behavior OF tb_dma IS + + constant DMA_NUM_CHANNEL : integer := 2; + constant DATA_WIDTH : integer := 32; + constant CLK_PERIOD : time := 10 ns; + signal CLK_O : std_logic := '1'; + signal RST_O : std_logic := '1'; + + -- Master + signal INT_O : std_logic; + signal CYC_O : std_logic; + signal STB_O : std_logic; + signal WE_O : std_logic; + signal SEL_O : unsigned(3 downto 0) := (others => '1'); + signal ACK_I : std_logic := '0'; + signal MRDY_O : std_logic := '1'; + signal SRDY_I : std_logic := '0'; + signal ADDR_O : unsigned(31 downto 0) := (others => '-'); + signal MDAT_I_64 : unsigned(63 downto 0) := (others => '-'); + signal MDAT_O_64 : unsigned(63 downto 0) := (others => '-'); + + signal MDAT_I : unsigned(31 downto 0) := (others => '-'); + signal MDAT_O : unsigned(31 downto 0) := (others => '-'); + + -- DMA controller + signal dma_master_req : unsigned(DMA_NUM_CHANNEL-1 downto 0); + signal dma_master_gnt : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + signal dma_req_rdy : unsigned(DMA_NUM_CHANNEL-1 downto 0); + signal dma_req_rw : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + signal dma_req_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + type array32_t is array (0 to DMA_NUM_CHANNEL-1) of unsigned(31 downto 0); + signal dma_req_addr : array32_t; + signal dma_req_addr_inc : array32_t; + signal dma_req_num_xfers : array32_t; + + signal dma_req_complete : unsigned(DMA_NUM_CHANNEL-1 downto 0); + signal dma_req_complete_ack : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + + signal dma_bus_source_en : unsigned(DMA_NUM_CHANNEL-1 downto 0); + signal dma_bus_cmd_cycle_finished : unsigned(DMA_NUM_CHANNEL-1 downto 0); + signal dma_bus_cmd_cycle_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + signal dma_bus_cmd_rdy : unsigned(DMA_NUM_CHANNEL-1 downto 0); + signal dma_bus_cmd_we : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + type array_bus_cmd_t is array (0 to DMA_NUM_CHANNEL-1) of bm_cmd_t; + signal dma_bus_cmd : array_bus_cmd_t; + + signal arb_idx : natural range 0 to DMA_NUM_CHANNEL-1; + + -- BUS Master controller + signal bus_source_en : std_logic; + signal bus_cmd_cycle_finished : std_logic; + signal bus_cmd_cycle_en : std_logic := '0'; + signal bus_cmd_rdy : std_logic; + signal bus_cmd_we : std_logic := '0'; + signal bus_cmd : bm_cmd_t; + + signal bus_din_rdy : std_logic; + signal bus_din_vld : std_logic := '0'; + signal bus_din : unsigned(DATA_WIDTH-1 downto 0) := (others => '-'); + + signal bus_dout : unsigned(31 downto 0); + signal bus_dout_vld : std_logic; + signal bus_dout_re : std_logic := '0'; + + signal rdy : std_logic := '0'; + signal read_reg : unsigned(31 downto 0) := (others => '-'); + + signal data_gen_reg : unsigned(31 downto 0) := (others => '-'); + signal data_gen_reg_inc : std_logic; + signal data_req : std_logic; + + type dma_write_source_t is (DATA_GEN, READ_FIFO); + signal dma_write_source : dma_write_source_t := DATA_GEN; + + -- Read FIFO + signal read_fifo_re : std_logic; + signal read_fifo_we : std_logic; + signal read_fifo_full : std_logic; + signal read_fifo_empty : std_logic; + signal read_fifo_din : unsigned(31 downto 0); + signal read_fifo_dout : unsigned(31 downto 0); + + type state_t is (IDLE, LA_SA, LA_SU, LU_SA, LU_SU, CC_SA, CC_SU); + signal state : state_t := IDLE; + + type ram_t is array (0 to 127) of unsigned(63 downto 0); + + signal ram64 : ram_t := + ( + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000", + X"0000_0000_0000_0000" + + ); + +BEGIN + + MDAT_I <= MDAT_I_64(31 downto 0); + MDAT_O_64 <= MDAT_O & MDAT_O; + +arbiter_proc: + process(CLK_O) + begin + if rising_edge(CLK_O) then + if RST_O = '1' then + dma_master_gnt <= (others => '0'); + arb_idx <= 0; + elsif dma_master_req(arb_idx) = '0' then + if arb_idx /= DMA_NUM_CHANNEL-1 then + arb_idx <= arb_idx + 1; + else + arb_idx <= 0; + end if; + else + dma_master_gnt <= (others => '0'); + dma_master_gnt(arb_idx) <= '1'; + end if; + end if; + end process; + +arbiter_mux: + process(dma_master_gnt, dma_bus_cmd, dma_bus_cmd_we, dma_bus_cmd_cycle_en) + variable v_bus_cmd_we : std_logic; + variable v_bus_cmd_cycle_en : std_logic; + variable v_bus_source_en : std_logic; + begin + v_bus_cmd_we := '0'; + v_bus_cmd_cycle_en := '0'; + v_bus_source_en := '0'; + for i in 0 to DMA_NUM_CHANNEL-1 loop + v_bus_cmd_we := v_bus_cmd_we or dma_bus_cmd_we(i); + v_bus_cmd_cycle_en := v_bus_cmd_cycle_en or dma_bus_cmd_cycle_en(i); + v_bus_source_en := v_bus_source_en or dma_bus_source_en(i); + if dma_master_gnt(i) = '1' then + bus_cmd <= dma_bus_cmd(i); + end if; + end loop; + bus_cmd_we <= v_bus_cmd_we; + bus_cmd_cycle_en <= v_bus_cmd_cycle_en; + bus_source_en <= v_bus_source_en; +end process; + +gen_uut: +for i in 0 to DMA_NUM_CHANNEL-1 generate + + dma_bus_cmd_cycle_finished(i) <= bus_cmd_cycle_finished; + dma_bus_cmd_rdy(i) <= bus_cmd_rdy; + + inst_uut : entity work.dma + Generic map + ( + DATA_WIDTH => 32, + XFER_CHUNK_SIZE => 64 + ) + Port map + ( + clk => CLK_O, + rst => RST_O, + + master_req => dma_master_req(i), + master_gnt => dma_master_gnt(i), + + req_rdy => dma_req_rdy(i), + req_rw => dma_req_rw(i), + req_en => dma_req_en(i), + req_addr => dma_req_addr(i), + req_addr_inc => dma_req_addr_inc(i), + req_num_xfers => dma_req_num_xfers(i), + + req_complete => dma_req_complete(i), + req_complete_ack => dma_req_complete_ack(i), + + -- busmaster control + bus_source_en => dma_bus_source_en(i), + + bus_cyc_complete => dma_bus_cmd_cycle_finished(i), + bus_cmd_rdy => dma_bus_cmd_rdy(i), + bus_cmd_we => dma_bus_cmd_we(i), + bus_cmd_cycle_en => dma_bus_cmd_cycle_en(i), + + -- busmaster command + bus_cmd_out => dma_bus_cmd(i) + ); + +end generate; + +-- Read buffer +inst_DMA_READ_FIFO: entity work.fifo_sync + GENERIC MAP + ( + addr_width => 10, + data_width => DATA_WIDTH, + do_last_read_update => true + ) + PORT MAP + ( + rst => RST_O, + clk => CLK_O, + we => read_fifo_we, + re => read_fifo_re, + fifo_full => read_fifo_full, + fifo_empty => read_fifo_empty, + fifo_afull => open, + fifo_aempty => open, + data_w => read_fifo_din, + data_r => read_fifo_dout + ); + +inst_busmaster_sync : entity work.busmaster_sync + GENERIC MAP + ( + DATA_WIDTH => DATA_WIDTH, + FIFO_DEPTH => 4 + ) + PORT MAP + ( + -- System signals + rst => RST_O, + clk => CLK_O, + + cmd_cycle_finished => bus_cmd_cycle_finished, + cmd_cycle_en => bus_cmd_cycle_en, + + cmd_rdy => bus_cmd_rdy, + cmd_we => bus_cmd_we, + cmd_in => bus_cmd, + + din_rdy => bus_din_rdy, + din_we => bus_din_vld, + din => bus_din, + + dout => bus_dout, + dout_vld => bus_dout_vld, + dout_re => bus_dout_re, + + -- JBUS Master signals + CYC_O => CYC_O, + STB_O => STB_O, + WE_O => WE_O, + SEL_O => SEL_O, + ACK_I => ACK_I, + SRDY_I => SRDY_I, + MRDY_O => MRDY_O, + ADDR_O => ADDR_O, + MDAT_I => MDAT_I, + MDAT_O => MDAT_O + ); + +rdy_GEN: process + begin +-- wait for 3*CLK_PERIOD/2; + wait until rising_edge(CLK_O); + rdy <= not rdy; + end process; + +CLK_GEN: process + begin + wait for CLK_PERIOD/2; + CLK_O <= not CLK_O; + end process; + +-- Slave + SRDY_I <= CYC_O; + + bus_dout_re <= '1' when dma_write_source = DATA_GEN else not read_fifo_full; + bus_din_vld <= bus_source_en when dma_write_source = DATA_GEN else (bus_source_en and not read_fifo_empty); + bus_din <= data_gen_reg when dma_write_source = DATA_GEN else read_fifo_dout; + data_gen_reg_inc <= (bus_din_rdy and bus_source_en) when dma_write_source = DATA_GEN else '0'; + read_fifo_re <= (bus_din_rdy and bus_source_en) when dma_write_source = READ_FIFO else '0'; + read_fifo_we <= bus_dout_vld; + read_fifo_din <= bus_dout; + + process(CLK_O) + begin + if rising_edge(CLK_O) then + if RST_O = '1' then + data_gen_reg <= X"BEEF_0000"; + elsif data_gen_reg_inc = '1' then + data_gen_reg <= data_gen_reg + X"0000_0004"; + end if; + end if; + end process; + + + process(CLK_O) + variable res: unsigned(63 downto 0); + variable ram_data : unsigned(63 downto 0); + begin + if rising_edge(CLK_O) then + if RST_O = '1' then + else + ACK_I <= '0'; + if (CYC_O and STB_O) = '1' then + if WE_O = '0' then + ACK_I <= '1'; + ram_data := ram64(to_integer(ADDR_O(31 downto 3))); + if ADDR_O(2) = '0' then + res := ram_data; + else + res := ram_data(31 downto 0) & ram_data(63 downto 32); + end if; + else -- WE=1 + ram_data := ram64(to_integer(ADDR_O(31 downto 3))); + -- ram_data := (others => '-'); + if ADDR_O(2) = '0' then + if SEL_O = "11111111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64; + elsif SEL_O = "00001111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(31 downto 0); + elsif SEL_O = "11110000" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(63 downto 32) & ram_data(31 downto 0); + end if; + else + if SEL_O = "11111111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & MDAT_O_64(63 downto 32); + elsif SEL_O = "00001111" then + ram64(to_integer(ADDR_O(31 downto 3))) <= MDAT_O_64(31 downto 0) & ram_data(31 downto 0); + elsif SEL_O = "11110000" then + ram64(to_integer(ADDR_O(31 downto 3))) <= ram_data(63 downto 32) & MDAT_O_64(63 downto 32); + end if; + end if; + end if; + end if; + MDAT_I_64 <= res; + end if; + end if; + end process; + + process(CLK_O) + begin + if rising_edge(CLK_O) then + if RST_O = '1' then + read_reg <= X"00000000"; + elsif bus_dout_vld = '1' then + read_reg <= bus_dout; + end if; + end if; + end process; + + +-- Master +STIMULUS: process + + procedure dma_wait_xfer_complete(ch : integer) is + begin + + dma_req_complete_ack(ch) <= '1'; + + wait until rising_edge(CLK_O) and dma_req_complete(ch) = '1'; + dma_req_complete_ack(ch) <= '0'; + + end procedure dma_wait_xfer_complete; + + procedure dma_request_write(ch : integer; addr_start, addr_incr, num_xfers : unsigned) is + begin + + dma_req_addr(ch) <= addr_start; + dma_req_addr_inc(ch) <= addr_incr; + dma_req_num_xfers(ch) <= num_xfers; + + dma_req_rw(ch) <= '1'; + dma_req_en(ch) <= '1'; + + wait until rising_edge(CLK_O) and dma_req_rdy(ch) = '1'; + dma_req_en(ch) <= '0'; + + end procedure dma_request_write; + + procedure dma_request_read(ch : integer; addr_start, addr_incr, num_xfers : unsigned) is + begin + + dma_req_addr(ch) <= addr_start; + dma_req_addr_inc(ch) <= addr_incr; + dma_req_num_xfers(ch) <= num_xfers; + + dma_req_rw(ch) <= '0'; + dma_req_en(ch) <= '1'; + + wait until rising_edge(CLK_O) and dma_req_rdy(ch) = '1'; + dma_req_en(ch) <= '0'; + + end procedure dma_request_read; + + begin + + wait for 6*CLK_PERIOD; + RST_O <= '0'; + wait for 60*CLK_PERIOD; + wait until rising_edge(CLK_O); + state <= IDLE; + + dma_request_write(0, X"00000000", X"00000004", X"00000040"); + dma_wait_xfer_complete(0); + dma_request_read(1, X"00000000", X"00000004", X"00000040"); + dma_wait_xfer_complete(1); + dma_write_source <= READ_FIFO; + dma_request_write(0, X"00000100", X"00000004", X"00000040"); + dma_wait_xfer_complete(0); + + state <= IDLE; + + wait; + + end process; + +END;