OpenCores
URL https://opencores.org/ocsvn/ax4lbr/ax4lbr/trunk

Subversion Repositories ax4lbr

[/] [ax4lbr/] [trunk/] [rtl/] [axil2ipb.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 wzab
-------------------------------------------------------------------------------
2
-- Title      : axil2ipb
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : axil2ipb.vhd
6
-- Author     : Wojciech M. Zabolotny  <wzab@ise.pw.edu.pl>
7
-- Company    : Institute of Electronic Systems, Warsaw University of Technology
8
-- Created    : 2016-04-24
9
-- Last update: 2016-05-14
10
-- License    : This is a PUBLIC DOMAIN code, published under
11
--              Creative Commons CC0 license
12
-- Platform   : 
13
-- Standard   : VHDL'93/02
14
-------------------------------------------------------------------------------
15
-- Description: AXI Lite -> IPbus bridge
16
-------------------------------------------------------------------------------
17
-- Copyright (c) 2016 
18
-------------------------------------------------------------------------------
19
-- Revisions  :
20
-- Date        Version  Author  Description
21
-- 2016-04-24  1.0      WZab    Created
22
-------------------------------------------------------------------------------
23
 
24
-- The AXI implementation is based on the description of AXI provided by
25
-- Rich Griffin in "Designing a Custom AXI-lite Slave Peripheral"
26
-- available at:
27
-- silica.com/wcsstore/Silica/Silica+Content+Library/Silica+Home/resources/71b10b18-9c9c-44c6-b62d-9a031b8f3df8/SILICA_Xilinx_Designing_a_custom_axi_slave_rev1.pdf
28
--
29
-- The IPbus implementation is based on the description provided in
30
-- "Notes on Firmware Implementation of an IPbus SoC Bus"
31
-- available at:
32
-- https://svnweb.cern.ch/trac/cactus/export/32752/trunk/doc/IPbus_firmware_notes.pdf
33
 
34
-------------------------------------------------------------------------------
35
-- Implementation details
36
-------------------------------------------------------------------------------
37
-- In the AXI bus the read and write accesses may be handled independently
38
-- In the IPbus they can't therefore we must provide an arbitration scheme.
39
-- We assume "Write before read"
40
-- 
41
-- We must avoid duplicated writes and reads (which may corruppt e.g.
42
-- FIFO slaves at IPbus!)
43
--
44
-- Additionally the IPbus uses the word adressing, while AXI uses the byte
45
-- addressing. That is handled by the function a_axi2ipb, which additionally
46
-- zeroes bits not used by the IPbus segment...
47
 
48
 
49
 
50
library IEEE;
51
use IEEE.STD_LOGIC_1164.all;
52
library work;
53
use work.ipbus.all;
54
 
55
entity axil2ipb is
56
 
57
  generic (
58
    ADRWIDTH : integer := 15);
59
 
60
  port (
61
    ---------------------------------------------------------------------------
62
    -- AXI Interface
63
    ---------------------------------------------------------------------------
64
    -- Clock and Reset
65
    S_AXI_ACLK    : in  std_logic;
66
    S_AXI_ARESETN : in  std_logic;
67
    -- Write Address Channel
68
    S_AXI_AWADDR  : in  std_logic_vector(ADRWIDTH-1 downto 0);
69
    S_AXI_AWVALID : in  std_logic;
70
    S_AXI_AWREADY : out std_logic;
71
    -- Write Data Channel
72
    S_AXI_WDATA   : in  std_logic_vector(31 downto 0);
73
    S_AXI_WSTRB   : in  std_logic_vector(3 downto 0);
74
    S_AXI_WVALID  : in  std_logic;
75
    S_AXI_WREADY  : out std_logic;
76
    -- Read Address Channel
77
    S_AXI_ARADDR  : in  std_logic_vector(ADRWIDTH-1 downto 0);
78
    S_AXI_ARVALID : in  std_logic;
79
    S_AXI_ARREADY : out std_logic;
80
    -- Read Data Channel
81
    S_AXI_RDATA   : out std_logic_vector(31 downto 0);
82
    S_AXI_RRESP   : out std_logic_vector(1 downto 0);
83
    S_AXI_RVALID  : out std_logic;
84
    S_AXI_RREADY  : in  std_logic;
85
    -- Write Response Channel
86
    S_AXI_BRESP   : out std_logic_vector(1 downto 0);
87
    S_AXI_BVALID  : out std_logic;
88
    S_AXI_BREADY  : in  std_logic;
89 4 wzab
    -- AWPROT and ARPROT - required by Altera
90
    --S_AXI_ARPROT  : in  std_logic_vector(2 downto 0);
91
    --S_AXI_AWPROT  : in  std_logic_vector(2 downto 0);
92 2 wzab
    -- Here we have the IPbus ports
93
    ipb_clk       : out std_logic;
94
    ipb_rst       : out std_logic;
95
    -- master_ipb_out - flattened due to Vivado inability to handle user types
96
    -- in BD
97
    ipb_addr      : out std_logic_vector(31 downto 0);
98
    ipb_wdata     : out std_logic_vector(31 downto 0);
99
    ipb_strobe    : out std_logic;
100
    ipb_write     : out std_logic;
101
    -- master_ipb_in -  flattened due to Vivado inability to handle user types
102
    -- in BD
103
    ipb_rdata     : in  std_logic_vector(31 downto 0);
104
    ipb_ack       : in  std_logic;
105
    ipb_err       :     std_logic
106
    );
107
 
108
end entity axil2ipb;
109
 
110
architecture beh of axil2ipb is
111
 
112
  function a_axi2ipb (
113
    constant axi_addr : std_logic_vector(ADRWIDTH-1 downto 0))
114
    return std_logic_vector is
115
    variable ipb_addr : std_logic_vector(31 downto 0);
116
  begin  -- function a_axi2ipb
117
    ipb_addr                      := (others => '0');
118
    -- Divide the address by 4 (we use word addresses, not the byte addresses)
119
    ipb_addr(ADRWIDTH-3 downto 0) := axi_addr(ADRWIDTH-1 downto 2);
120
    return ipb_addr;
121
  end function a_axi2ipb;
122
 
123
  signal master_ipb_out                                     : ipb_wbus;
124
  signal master_ipb_in                                      : ipb_rbus;
125
  signal read_wait, read_wait_in, write_wait, write_wait_in : boolean                       := false;
126
  signal rdata, rdata_in, addr, addr_in, wdata, wdata_in    : std_logic_vector(31 downto 0) := (others => '0');
127
  signal bresp, rresp, bresp_in, rresp_in                   : std_logic_vector(1 downto 0)  := "00";
128
  signal del_bresp, del_rresp, del_bresp_in, del_rresp_in   : boolean                       := false;
129
 
130
begin  -- architecture beh
131
 
132
  ipb_clk    <= S_AXI_ACLK;
133
  ipb_rst    <= not S_AXI_ARESETN;
134
  -- We keep the master_ipb... signals internally in hope, that one day
135
  -- Xilinx/Vivado will be able to handle user defined records in ports of BD blocks...
136
  ipb_addr   <= master_ipb_out.ipb_addr;
137
  ipb_wdata  <= master_ipb_out.ipb_wdata;
138
  ipb_strobe <= master_ipb_out.ipb_strobe;
139
  ipb_write  <= master_ipb_out.ipb_write;
140
 
141
  master_ipb_in.ipb_rdata <= ipb_rdata;
142
  master_ipb_in.ipb_ack   <= ipb_ack;
143
  master_ipb_in.ipb_err   <= ipb_err;
144
 
145
  qq : process (S_AXI_ARADDR, S_AXI_ARVALID, S_AXI_AWADDR, S_AXI_AWVALID,
146
                S_AXI_BREADY, S_AXI_RREADY, S_AXI_WDATA, S_AXI_WSTRB,
147
                S_AXI_WVALID, addr, bresp, del_bresp, del_rresp, master_ipb_in,
148
                rdata, read_wait, rresp, wdata, write_wait) is
149
    variable is_read, is_write : boolean := false;
150
  begin  -- process qq
151
    -- Defaults
152
    is_read                   := false;
153
    is_write                  := false;
154
    master_ipb_out.ipb_strobe <= '0';
155
    master_ipb_out.ipb_addr   <= (others => '0');
156
    master_ipb_out.ipb_wdata  <= (others => '0');
157
    master_ipb_out.ipb_write  <= '0';
158
    -- Flags handling delayed acceptance of results
159
    del_bresp_in              <= del_bresp;
160
    del_rresp_in              <= del_rresp;
161
    -- Registers storing the results
162
    bresp_in                  <= bresp;
163
    rresp_in                  <= rresp;
164
    rdata_in                  <= rdata;
165
    wdata_in                  <= wdata;
166
    read_wait_in              <= read_wait;
167
    write_wait_in             <= write_wait;
168
    addr_in                   <= addr;
169
    S_AXI_BVALID              <= '0';
170
    S_AXI_BRESP               <= (others => '0');
171
    S_AXI_ARREADY             <= '0';
172
    S_AXI_RVALID              <= '0';
173
    S_AXI_RDATA               <= (others => '0');
174
    S_AXI_RRESP               <= (others => '0');
175
    S_AXI_AWREADY             <= '0';
176
    S_AXI_WREADY              <= '0';
177
 
178
    -- Real processing
179
    -- Handling of delayed responses
180
    if del_bresp then
181
      S_AXI_BRESP  <= bresp;
182
      S_AXI_BVALID <= '1';
183
      if S_AXI_BREADY = '1' then
184
        del_bresp_in <= false;
185
      end if;
186
    elsif del_rresp then
187
      S_AXI_RRESP  <= rresp;
188
      S_AXI_RDATA  <= rdata;
189
      S_AXI_RVALID <= '1';
190
      if S_AXI_RREADY = '1' then
191
        del_rresp_in <= false;
192
      end if;
193
    -- Handling of new transactions
194
    elsif (S_AXI_AWVALID = '1' and S_AXI_WVALID = '1') or write_wait then
195
      is_write := true;
196
    elsif S_AXI_ARVALID = '1' or read_wait then
197
      is_read := true;
198
    end if;
199
    -- Set the IPbus signals
200
    if is_write then
201
      -- Check if this is a new transmission
202
      if S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and write_wait = false then
203
        -- This is a new transmission
204
        -- Check if this is a correct 32-bit write
205
        if S_AXI_WSTRB /= "1111" then
206
          -- Erroneouos write. If slave is ready to accept status, inform about it
207
          S_AXI_AWREADY <= '1';
208
          S_AXI_WREADY  <= '1';
209
          S_AXI_BRESP   <= "10";
210
          S_AXI_BVALID  <= '1';
211
          if S_AXI_BREADY = '0' then
212
            -- Prepare delayed response
213
            bresp_in     <= "10";
214
            del_bresp_in <= true;
215
          end if;
216
        else
217
          -- Correct write
218
          -- Write transaction on IPbus
219
          master_ipb_out.ipb_addr   <= a_axi2ipb(S_AXI_AWADDR);
220
          master_ipb_out.ipb_wdata  <= S_AXI_WDATA;
221
          master_ipb_out.ipb_strobe <= '1';
222
          master_ipb_out.ipb_write  <= '1';
223
          -- Store data for the next cycles
224
          addr_in                   <= a_axi2ipb(S_AXI_AWADDR);
225
          wdata_in                  <= S_AXI_WDATA;
226
          S_AXI_AWREADY             <= '1';
227
          S_AXI_WREADY              <= '1';
228
          write_wait_in             <= true;
229
        end if;
230
      else
231
        -- This the next cycle of the write transmission
232
        master_ipb_out.ipb_addr   <= addr;
233
        master_ipb_out.ipb_wdata  <= wdata;
234
        master_ipb_out.ipb_strobe <= '1';
235
        master_ipb_out.ipb_write  <= '1';
236
      end if;
237
      -- Check the slave response
238
      if master_ipb_in.ipb_err = '1' then
239
        write_wait_in <= false;
240
        S_AXI_BRESP   <= "10";
241
        S_AXI_BVALID  <= '1';
242
        if S_AXI_BREADY = '0' then
243
          -- Prepare delayed response
244
          bresp_in     <= "10";
245
          del_bresp_in <= true;
246
        end if;
247
      elsif master_ipb_in.ipb_ack = '1' then
248
        write_wait_in <= false;
249
        S_AXI_BRESP   <= "00";
250
        S_AXI_BVALID  <= '1';
251
        if S_AXI_BREADY = '0' then
252
          -- Prepare delayed response
253
          bresp_in     <= "00";
254
          del_bresp_in <= true;
255
        end if;
256
      end if;
257
    elsif is_read then
258
      -- Read transaction on IPbus
259
      if S_AXI_ARVALID = '1' and read_wait = false then
260
        addr_in                 <= a_axi2ipb(S_AXI_ARADDR);
261
        master_ipb_out.ipb_addr <= a_axi2ipb(S_AXI_ARADDR);
262
        S_AXI_ARREADY           <= '1';
263
        -- Remember that we are in read
264
        read_wait_in            <= true;
265
      else
266
        master_ipb_out.ipb_addr <= addr;
267
      end if;
268
      master_ipb_out.ipb_strobe <= '1';
269
      master_ipb_out.ipb_write  <= '0';
270
      -- Check the slave response
271
      if master_ipb_in.ipb_err = '1' then
272
        S_AXI_RRESP  <= "10";
273
        S_AXI_RDATA  <= master_ipb_in.ipb_rdata;
274
        S_AXI_RVALID <= '1';
275
        read_wait_in <= false;
276
        if S_AXI_RREADY = '0' then
277
          -- Prepare delayed response
278
          rresp_in     <= "10";
279
          rdata_in     <= master_ipb_in.ipb_rdata;
280
          del_rresp_in <= true;
281
        end if;
282
      elsif master_ipb_in.ipb_ack = '1' then
283
        S_AXI_RRESP  <= "00";
284
        S_AXI_RDATA  <= master_ipb_in.ipb_rdata;
285
        S_AXI_RVALID <= '1';
286
        read_wait_in <= false;
287
        if S_AXI_RREADY = '0' then
288
          -- Prepare delayed response
289
          rresp_in     <= "00";
290
          rdata_in     <= master_ipb_in.ipb_rdata;
291
          del_rresp_in <= true;
292
        end if;
293
      end if;
294
    end if;
295
  end process qq;
296
 
297
  process (S_AXI_ACLK) is
298
  begin  -- process
299
    if S_AXI_ACLK'event and S_AXI_ACLK = '1' then  -- rising clock edge
300
      if S_AXI_ARESETN = '0' then       -- synchronous reset (active low)
301
        del_rresp  <= false;
302
        del_bresp  <= false;
303
        rdata      <= (others => '0');
304
        wdata      <= (others => '0');
305
        rresp      <= (others => '0');
306
        bresp      <= (others => '0');
307
        addr       <= (others => '0');
308
        read_wait  <= false;
309
        write_wait <= false;
310
      else
311
        del_rresp  <= del_rresp_in;
312
        del_bresp  <= del_bresp_in;
313
        addr       <= addr_in;
314
        rdata      <= rdata_in;
315
        wdata      <= wdata_in;
316
        rresp      <= rresp_in;
317
        bresp      <= bresp_in;
318
        read_wait  <= read_wait_in;
319
        write_wait <= write_wait_in;
320
      end if;
321
    end if;
322
  end process;
323
 
324
 
325
end architecture beh;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.