----------------------------------------------------------------------- -- $Header: D:\usr\cvsroot/VHDL/lib/JBUS/src/tb_dmac.vhd,v 1.2 2013/05/28 11:23:15 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 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_start : unsigned(DMA_NUM_CHANNEL-1 downto 0); signal dma_active : unsigned(DMA_NUM_CHANNEL-1 downto 0); signal dma_end : 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_start => dma_start(i), dma_active => dma_active(i), dma_end => dma_end(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;