diff --git a/lib/JBUS/sim/tb_dmac.fdo b/lib/JBUS/sim/tb_dmac.fdo new file mode 100644 index 0000000..ca0cbf8 --- /dev/null +++ b/lib/JBUS/sim/tb_dmac.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/dmac.vhd" +vcom -explicit -93 "../src/tb_dmac.vhd" +vsim -t 1ps -lib work tb_dmac +view wave +do {tb_dmac.wdo} +view structure +view signals + +run 6us diff --git a/lib/JBUS/sim/tb_dmac.wdo b/lib/JBUS/sim/tb_dmac.wdo new file mode 100644 index 0000000..6a0becd --- /dev/null +++ b/lib/JBUS/sim/tb_dmac.wdo @@ -0,0 +1,173 @@ +onerror {resume} +quietly WaveActivateNextPane {} 0 +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/read_reg +add wave -noupdate -format Literal /tb_dmac/dma_master_req +add wave -noupdate -format Literal /tb_dmac/dma_master_gnt +add wave -noupdate -format Literal /tb_dmac/dma_req_rdy +add wave -noupdate -format Literal /tb_dmac/dma_req_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/dma_req_addr +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/dma_req_num_xfers +add wave -noupdate -format Literal /tb_dmac/dma_req_complete +add wave -noupdate -format Literal /tb_dmac/dma_req_complete_ack +add wave -noupdate -format Logic /tb_dmac/bus_cmd_cycle_finished +add wave -noupdate -format Logic /tb_dmac/bus_cmd_cycle_en +add wave -noupdate -format Logic /tb_dmac/bus_cmd_rdy +add wave -noupdate -format Logic /tb_dmac/bus_cmd_we +add wave -noupdate -format Literal -radix hexadecimal -expand /tb_dmac/bus_cmd +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/bus_dout +add wave -noupdate -format Logic /tb_dmac/bus_dout_vld +add wave -noupdate -format Logic /tb_dmac/bus_dout_re +add wave -noupdate -format Logic /tb_dmac/bus_din_rdy +add wave -noupdate -format Logic /tb_dmac/bus_din_vld +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/bus_din +add wave -noupdate -divider Busmaster +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_we +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/cmd_in +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/din +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/din_rdy +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/din_we +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/dout +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/dout_vld +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/dout_re +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/ack_i +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/srdy_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/mdat_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/mdat_o +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/addr_o +add wave -noupdate -format Literal /tb_dmac/inst_busmaster_sync/sel_o +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/we_o +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cyc_o +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/stb_o +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/mrdy_o +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/cmd_fifo_din +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/inst_busmaster_sync/cmd_fifo_dout +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_fifo_re +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_fifo_we +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_fifo_full +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_fifo_empty +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/read_fifo_re +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/read_fifo_we +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/read_fifo_full +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/read_fifo_empty +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/write_fifo_re +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/write_fifo_we +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/write_fifo_full +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/write_fifo_empty +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cycle_busy +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_en +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/cmd_read_en +add wave -noupdate -format Literal /tb_dmac/inst_busmaster_sync/read_cnt +add wave -noupdate -format Logic /tb_dmac/inst_busmaster_sync/write +add wave -noupdate -divider JBUS +add wave -noupdate -format Logic /tb_dmac/clk_o +add wave -noupdate -format Logic /tb_dmac/rst_o +add wave -noupdate -format Logic /tb_dmac/int_o +add wave -noupdate -format Logic /tb_dmac/cyc_o +add wave -noupdate -format Logic /tb_dmac/stb_o +add wave -noupdate -format Logic /tb_dmac/we_o +add wave -noupdate -format Literal /tb_dmac/sel_o +add wave -noupdate -format Logic /tb_dmac/ack_i +add wave -noupdate -format Logic /tb_dmac/mrdy_o +add wave -noupdate -format Logic /tb_dmac/srdy_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/addr_o +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/mdat_i +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/mdat_o +add wave -noupdate -divider {DMA 0} +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/clk +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/rst +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/master_req +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/master_gnt +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/dma_active +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_rdy +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_en +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_rw +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/req_addr_start +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/req_num_xfers +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_addr_auto_inc +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_complete +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_complete_ack +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/bus_cyc_complete +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/bus_cmd_rdy +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/bus_cmd_we +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/bus_cmd_cycle_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/bus_cmd_out +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/start_en +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/finish_en +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/complete +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/addr_inc_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/addr +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/rw +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/req_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/req_count_next +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/req_count_rdy +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/chunk_count_rst +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/chunk_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/chunk_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__0/inst_uut/chunk_count_next +add wave -noupdate -format Logic /tb_dmac/gen_uut__0/inst_uut/chunk_count_rdy +add wave -noupdate -format Literal /tb_dmac/gen_uut__0/inst_uut/s +add wave -noupdate -divider {DMA 1} +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/clk +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/rst +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/master_req +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/master_gnt +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/dma_active +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_rdy +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_en +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_rw +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/req_addr_start +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/req_num_xfers +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_addr_auto_inc +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_complete +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_complete_ack +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/bus_cyc_complete +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/bus_cmd_rdy +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/bus_cmd_we +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/bus_cmd_cycle_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/bus_cmd_out +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/start_en +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/finish_en +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/complete +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/addr_inc_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/addr +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/rw +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/req_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/req_count_next +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/req_count_rdy +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/chunk_count_rst +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/chunk_count_en +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/chunk_count +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/gen_uut__1/inst_uut/chunk_count_next +add wave -noupdate -format Logic /tb_dmac/gen_uut__1/inst_uut/chunk_count_rdy +add wave -noupdate -format Literal /tb_dmac/gen_uut__1/inst_uut/s +add wave -noupdate -divider {Read FIFO} +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/data_gen_reg +add wave -noupdate -format Logic /tb_dmac/data_gen_reg_inc +add wave -noupdate -format Literal /tb_dmac/dma_write_source +add wave -noupdate -format Logic /tb_dmac/read_fifo_re +add wave -noupdate -format Logic /tb_dmac/read_fifo_we +add wave -noupdate -format Logic /tb_dmac/read_fifo_full +add wave -noupdate -format Logic /tb_dmac/read_fifo_empty +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/read_fifo_din +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/read_fifo_dout +add wave -noupdate -divider RAM +add wave -noupdate -format Literal /tb_dmac/state +add wave -noupdate -format Literal -radix hexadecimal /tb_dmac/ram64 +TreeUpdate [SetDefaultTree] +WaveRestoreCursors {{Cursor 1} {3159968 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 {0 ps} {6300 ns} diff --git a/lib/JBUS/src/dmac.vhd b/lib/JBUS/src/dmac.vhd new file mode 100644 index 0000000..49845d9 --- /dev/null +++ b/lib/JBUS/src/dmac.vhd @@ -0,0 +1,217 @@ +----------------------------------------------------------------------- +-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/dmac.vhd,v 1.1 2013-05-28 10:18:02 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 dmac 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; + + dma_active : out std_logic; + + req_rdy : out std_logic; + req_en : in std_logic; + req_rw : in std_logic; + req_addr_start : in unsigned(31 downto 0); + req_num_xfers : in unsigned(31 downto 0); + req_addr_auto_inc : in std_logic; + + req_complete : out std_logic; + req_complete_ack : in std_logic; + + -- busmaster control + 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 dmac; + +architecture Behavioral of dmac is + + signal start_en : std_logic; + signal finish_en : std_logic; + signal complete : std_logic; + signal addr_inc_en : std_logic; + signal addr : unsigned(31 downto 0); + signal rw : std_logic; + + 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, FINISH); + signal s, sn : state_t; + +begin + + bus_cmd_out.addr <= addr; + bus_cmd_out.sel <= (others => '1'); + 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, 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'; + dma_active <= '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 + sn <= XFER; + end if; + + when XFER => + dma_active <= '1'; + 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 + rw <= req_rw; + addr <= req_addr_start; + addr_inc_en <= req_addr_auto_inc; + elsif req_count_en = '1' and addr_inc_en = '1' then + addr <= addr + DATA_WIDTH/8; + 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_dmac.vhd b/lib/JBUS/src/tb_dmac.vhd new file mode 100644 index 0000000..f492d57 --- /dev/null +++ b/lib/JBUS/src/tb_dmac.vhd @@ -0,0 +1,537 @@ +----------------------------------------------------------------------- +-- $Header: /tmp/cvsroot/VHDL/lib/JBUS/src/tb_dmac.vhd,v 1.1 2013-05-28 10:18:02 jens Exp $ +----------------------------------------------------------------------- + +LIBRARY ieee; +use IEEE.STD_LOGIC_1164.ALL; +USE ieee.numeric_std.ALL; + +use work.busmaster_types.all; + +ENTITY tb_dmac IS +END tb_dmac; + +ARCHITECTURE behavior OF tb_dmac IS + + constant CLK_PERIOD : time := 10 ns; + constant DATA_WIDTH : integer := 32; + + constant DMA_NUM_CHANNEL : integer := 2; + constant DMA_CH_WRITE : integer := 0; + constant DMA_CH_READ : integer := 1; + constant DMA_RW_CONF : unsigned(DMA_NUM_CHANNEL-1 downto 0) := "01"; + + 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_en : unsigned(DMA_NUM_CHANNEL-1 downto 0) := (others => '0'); + signal dma_req_addr_auto_inc : unsigned(DMA_NUM_CHANNEL-1 downto 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_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_active : 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_din_re : 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; + begin + v_bus_cmd_we := '0'; + v_bus_cmd_cycle_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); + 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; +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.dmac + Generic map + ( + DATA_WIDTH => 32, + XFER_CHUNK_SIZE => 8 + ) + 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_en => dma_req_en(i), + req_rw => DMA_RW_CONF(i), + req_addr_auto_inc => dma_req_addr_auto_inc(i), + req_addr_start => dma_req_addr(i), + req_num_xfers => dma_req_num_xfers(i), + + req_complete => dma_req_complete(i), + req_complete_ack => dma_req_complete_ack(i), + + dma_active => dma_active(i), + + -- busmaster control + 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 <= dma_active(DMA_CH_WRITE) when dma_write_source = DATA_GEN else (dma_active(DMA_CH_WRITE) 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 dma_active(DMA_CH_WRITE)) when dma_write_source = DATA_GEN else '0'; + read_fifo_re <= (bus_din_rdy and dma_active(DMA_CH_WRITE)) 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(ch : integer; addr_start, num_xfers : unsigned) is + begin + + dma_req_addr_auto_inc(ch) <= '1'; + dma_req_addr(ch) <= addr_start; + dma_req_num_xfers(ch) <= num_xfers; + + 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; + + begin + + wait for 6*CLK_PERIOD; + RST_O <= '0'; + wait for 60*CLK_PERIOD; + wait until rising_edge(CLK_O); + state <= IDLE; + + dma_request(DMA_CH_WRITE, X"00000000", X"00000040"); +-- dma_wait_xfer_complete(DMA_CH_WRITE); + dma_request(DMA_CH_READ, X"00000000", X"00000040"); + dma_wait_xfer_complete(DMA_CH_READ); + dma_write_source <= READ_FIFO; + dma_request(DMA_CH_WRITE, X"00000100", X"00000040"); +-- dma_wait_xfer_complete(DMA_CH_WRITE); + + state <= IDLE; + + wait; + + end process; + +END;