summaryrefslogtreecommitdiffstats
path: root/fpga/hp_lcd_driver/fifo_to_axi.vhdl
blob: c527ea1550d331185786b986c224252a6f7d5f5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;

entity fifo_to_axi is
    generic (
        ADDR_WIDTH : integer               := 32;
        START      : unsigned(31 downto 0) := x"FFFC0000";
        SIZE       : unsigned(31 downto 0) := x"00040000"
        );
    port (
        aclk    : in std_logic;
        aresetn : in std_logic;

        run : in std_logic;

        fifo_empty : in  std_logic;
        fifo_rdata : in  std_logic_vector(64 downto 0);
        fifo_rd_en : out std_logic;

        axi_awaddr  : out std_logic_vector (ADDR_WIDTH-1 downto 0);
        axi_awvalid : out std_logic;
        axi_awready : in  std_logic;
        axi_wdata   : out std_logic_vector (63 downto 0);
        axi_wstrb   : out std_logic_vector (7 downto 0);
        axi_wvalid  : out std_logic;
        axi_wready  : in  std_logic;
        axi_bvalid  : in  std_logic;
        axi_bready  : out std_logic
        );
end entity fifo_to_axi;

architecture Behavioral of fifo_to_axi is

    --signal lazy         : std_logic_vector(63 downto 0);
    signal addr         : std_logic_vector(ADDR_WIDTH-1 downto 0) := std_logic_vector(START);
    signal data         : std_logic_vector(63 downto 0);
    signal do_bus_cycle : std_logic;
    signal s_run        : std_logic;

begin


    run_sync : entity work.synchronizer
        generic map(stages => 2)
        port map (
            clk => aclk,
            i   => run,
            o   => s_run
            );



    axi_bready <= do_bus_cycle;
    axi_wdata  <= data;
    axi_wstrb  <= (others => '1');
    axi_awaddr <= addr;

    --XXX this is moderately budget, it could do with a tonne of pipelining

    process (aclk)
    begin
        if rising_edge(aclk) then
            if aresetn = '0' then
                axi_awvalid  <= '0';
                axi_wvalid   <= '0';
                do_bus_cycle <= '0';
                fifo_rd_en   <= '0';
                addr         <= std_logic_vector(START);
            elsif run = '1' and do_bus_cycle = '1' then
                fifo_rd_en <= '0';

                if axi_bvalid = '1' then
                    do_bus_cycle <= '0';
                    if addr /= std_logic_vector(START+SIZE-to_unsigned(8, ADDR_WIDTH)) then
                        addr <= std_logic_vector(unsigned(addr) +to_unsigned(8, ADDR_WIDTH));
                    end if;
                    axi_awvalid <= '0';
                    axi_wvalid  <= '0';
                end if;
                if axi_awready = '1' then
                    axi_awvalid <= '0';
                end if;
                if axi_wready = '1' then
                    axi_wvalid <= '0';
                end if;
            elsif do_bus_cycle = '0' then

                if fifo_empty = '0' then
                    data <= fifo_rdata (63 downto 0);
                    if fifo_rdata(64) = '1' then
                        addr <= std_logic_vector(START);
                    end if;
                    fifo_rd_en   <= '1';
                    do_bus_cycle <= '1';
                    axi_awvalid  <= '1';
                    axi_wvalid   <= '1';
                end if;
            end if;

        end if;

    end process;

end Behavioral;