summaryrefslogtreecommitdiffstats
path: root/zpu/rtl/dualport_ram_ahb_wrapper.vhd
blob: 941a6ecab5c043474d8dc154a5237ead28b5a13d (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

library ieee;
use ieee.std_logic_1164.all;

library grlib;
use grlib.amba.all;
use grlib.stdlib.all;
use grlib.devices.all;

library hzdr;
use hzdr.devices_hzdr.all;


entity dualport_ram_ahb_wrapper is
    generic (
        hindex  : integer := 0;
        haddr   : integer := 0;
        hmask   : integer := 16#fff#
    );
    port (
        clk    : in std_ulogic;
        reset  : in std_ulogic;
        -- ahb
        ahbsi   : in  ahb_slv_in_type;
        ahbso   : out ahb_slv_out_type
    );
end entity dualport_ram_ahb_wrapper;



library ieee;
use ieee.std_logic_1164;

library zpu;
use zpu.zpu_config.all;
use zpu.zpupkg.all; -- wordsize
use zpu.zpupkg.dualport_ram;


architecture rtl of dualport_ram_ahb_wrapper is

    constant hconfig : ahb_config_type := (
        0 => ahb_device_reg ( VENDOR_HZDR, HZDR_ZPU_MEM_WRAPPER, 0, maxAddrBitBRAM+2, 0),
        4 => ahb_membar(haddr, '1', '1', hmask),
        others => zero32);

    type reg_t is record
        hwrite : std_ulogic;
        hready : std_ulogic;
        hsel   : std_ulogic;
        we     : std_ulogic;
        addr   : std_logic_vector(maxAddrBitBRAM downto minAddrBit);
        haddr  : std_logic_vector(maxAddrBitBRAM downto minAddrBit);
        data   : std_logic_vector(wordSize-1 downto 0);
    end record;
    constant default_reg_c : reg_t := (
        hwrite  => '0',
        hready  => '0',
        hsel    => '0',
        we      => '0',
        addr    => (others => '0'),
        haddr   => (others => '0'),
        data    => (others => '0')
    );

    type src_t is record
        data   : std_logic_vector(wordSize-1 downto 0);
    end record;

    signal r, r_in : reg_t;
    signal s       : src_t;
    signal we      : std_logic;
    signal addr    : std_logic_vector(maxAddrBitBRAM downto minAddrBit);

begin
  
  dualport_ram_i0: dualport_ram
    port map (
      clk             => clk,              -- : in  std_logic;
      memAWriteEnable => we,               -- : in  std_logic;
      memAAddr        => addr,             -- : in  std_logic_vector(maxAddrBitBRAM downto minAddrBit);
      memAWrite       => ahbsi.hwdata,     -- : in  std_logic_vector(wordSize-1 downto 0);
      memARead        => s.data,           -- : out std_logic_vector(wordSize-1 downto 0);
      memBWriteEnable => '0',              -- : in  std_logic;
      memBAddr        => (others => '0'),  -- : in  std_logic_vector(maxAddrBitBRAM downto minAddrBit);
      memBWrite       => (others => '0'),  -- : in  std_logic_vector(wordSize-1 downto 0);
      memBRead        => open              -- : out std_logic_vector(wordSize-1 downto 0)
      );

    comb: process(ahbsi, r, s)
        variable v: reg_t;
    begin
        v            := r;
        ahbso.hready <= v.hready;

        v.hready     := '1';
        v.we         := '0';

        if (r.hwrite or not r.hready) = '1' then
            v.haddr  := v.addr;
        else
            v.haddr  := ahbsi.haddr(maxAddrBitBRAM downto minAddrBit);
        end if;
                     
        if ahbsi.hready = '1' then -- react only when bus is ready
            v.hsel   := ahbsi.hsel( hindex) and ahbsi.htrans(1);
            v.hwrite := ahbsi.hwrite and v.hsel;
            v.addr   := ahbsi.haddr(maxAddrBitBRAM downto minAddrBit);
        end if;

        if r.hwrite = '1' then
            v.we     := '1';
            v.hready := not (v.hsel and not ahbsi.hwrite);
            v.hwrite := v.hwrite and v.hready;
        end if;

        v.data       := ahbsi.hwdata;
        
        ahbso.hrdata <= s.data;
        if is_x( v.haddr) then
            addr     <= (others => '0');
        else
            addr     <= v.haddr;
        end if;
        we           <= v.we;
        r_in         <= v;
    end process;

    seq: process
    begin
        wait until rising_edge( clk);
        r <= r_in;
        if reset = '1' then
            r <= default_reg_c;
        end if;
    end process;
  
    ahbso.hresp   <= "00"; 
    ahbso.hsplit  <= (others => '0'); 
    ahbso.hirq    <= (others => '0');
    ahbso.hcache  <= '1';
    ahbso.hconfig <= hconfig;
    ahbso.hindex  <= hindex;

    -- pragma translate_off
    bootmsg : report_version 
      generic map ("zpumem" & tost(hindex) &
        ": ZPU Memory AHB Wrapper, " & tost((2**(maxAddrBitBRAM + 1))/1024 ) & " kbytes addressable (" & tost( bram_words) & " words)");
    -- pragma translate_on

end architecture rtl;
OpenPOWER on IntegriCloud