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

Subversion Repositories ax4lbr

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 wzab
-------------------------------------------------------------------------------
2
-- Title      : axil2wb
3
-- Project    : 
4
-------------------------------------------------------------------------------
5 3 wzab
-- File       : axil2wb.vhd
6 2 wzab
-- 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 3 wzab
-- Last update: 2016-05-15
10 2 wzab
-- 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 -> WB bridge
16
-------------------------------------------------------------------------------
17
-- Copyright (c) 2016 
18
-------------------------------------------------------------------------------
19
-- Revisions  :
20
-- Date        Version  Author  Description
21
-- 2016-05-13  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
-------------------------------------------------------------------------------
30
-- Implementation details
31
-------------------------------------------------------------------------------
32
-- In the AXI bus the read and write accesses may be handled independently
33
-- In the IPbus they can't therefore we must provide an arbitration scheme.
34
-- We assume "Write before read"
35
-- 
36
-- We must avoid duplicated writes and reads (which may corruppt e.g.
37
-- FIFO slaves at IPbus!)
38
--
39
-- Additionally the IPbus uses the word adressing, while AXI uses the byte
40
-- addressing. That is handled by the function a_axi2ipb, which additionally
41
-- zeroes bits not used by the IPbus segment...
42
 
43
 
44
 
45
library IEEE;
46
use IEEE.STD_LOGIC_1164.all;
47
library work;
48
 
49
entity axil2wb is
50
 
51
  generic (
52
    ADRWIDTH  : integer := 15;
53
    DATAWIDTH : integer := 32);
54
 
55
  port (
56
    ---------------------------------------------------------------------------
57
    -- AXI Interface
58
    ---------------------------------------------------------------------------
59
    -- Clock and Reset
60
    S_AXI_ACLK    : in  std_logic;
61
    S_AXI_ARESETN : in  std_logic;
62
    -- Write Address Channel
63
    S_AXI_AWADDR  : in  std_logic_vector(ADRWIDTH-1 downto 0);
64
    S_AXI_AWVALID : in  std_logic;
65
    S_AXI_AWREADY : out std_logic;
66
    -- Write Data Channel
67
    S_AXI_WDATA   : in  std_logic_vector(31 downto 0);
68
    S_AXI_WSTRB   : in  std_logic_vector(3 downto 0);
69
    S_AXI_WVALID  : in  std_logic;
70
    S_AXI_WREADY  : out std_logic;
71
    -- Read Address Channel
72
    S_AXI_ARADDR  : in  std_logic_vector(ADRWIDTH-1 downto 0);
73
    S_AXI_ARVALID : in  std_logic;
74
    S_AXI_ARREADY : out std_logic;
75
    -- Read Data Channel
76
    S_AXI_RDATA   : out std_logic_vector(31 downto 0);
77
    S_AXI_RRESP   : out std_logic_vector(1 downto 0);
78
    S_AXI_RVALID  : out std_logic;
79
    S_AXI_RREADY  : in  std_logic;
80
    -- Write Response Channel
81
    S_AXI_BRESP   : out std_logic_vector(1 downto 0);
82
    S_AXI_BVALID  : out std_logic;
83
    S_AXI_BREADY  : in  std_logic;
84 4 wzab
    -- AWPROT and ARPROT - required by Altera
85
    --S_AXI_ARPROT  : in  std_logic_vector(2 downto 0);
86
    --S_AXI_AWPROT  : in  std_logic_vector(2 downto 0);
87 2 wzab
    -- Here we have the WB ports
88
    -- The clock and reset are comming from AXI!
89
    wb_clk_o      : out std_logic;
90
    wb_rst_o      : out std_logic;
91
    -- master_ipb_out - flattened due to Vivado inability to handle user types
92
    -- in BD
93
    wb_addr_o     : out std_logic_vector(31 downto 0);
94
    wb_dat_o      : out std_logic_vector(31 downto 0);
95
    wb_we_o       : out std_logic;
96
    wb_sel_o      : out std_logic_vector(3 downto 0);
97
    wb_stb_o      : out std_logic;
98
    wb_cyc_o      : out std_logic;
99
    -- master_ipb_in -  flattened due to Vivado inability to handle user types
100
    -- in BD
101
    wb_dat_i      : in  std_logic_vector(31 downto 0);
102
    wb_err_i      : in  std_logic;  -- Not used in figure 1-2 in specification!
103
    wb_ack_i      : in  std_logic
104
    );
105
 
106
end entity axil2wb;
107
 
108
architecture beh of axil2wb is
109
 
110
  function a_axi2wb (
111
    constant axi_addr : std_logic_vector(ADRWIDTH-1 downto 0))
112
    return std_logic_vector is
113
    variable wb_addr : std_logic_vector(31 downto 0);
114
  begin  -- function a_axi2wb
115
    wb_addr                      := (others => '0');
116
    -- Divide the address by 4 (we use word addresses, not the byte addresses)
117
    wb_addr(ADRWIDTH-3 downto 0) := axi_addr(ADRWIDTH-1 downto 2);
118
    return wb_addr;
119
  end function a_axi2wb;
120
 
121
  signal read_wait, read_wait_in, write_wait, write_wait_in : boolean                                := false;
122
  signal rdata, rdata_in, addr, addr_in, wdata, wdata_in    : std_logic_vector(DATAWIDTH-1 downto 0) := (others => '0');
123
  signal bresp, rresp, bresp_in, rresp_in                   : std_logic_vector(1 downto 0)           := "00";
124
  signal del_bresp, del_rresp, del_bresp_in, del_rresp_in   : boolean                                := false;
125
 
126
begin  -- architecture beh
127
 
128
  wb_clk_o <= S_AXI_ACLK;
129
  wb_rst_o <= S_AXI_ARESETN;
130
  wb_sel_o <= (others => '1');          -- We support only whole word accesses
131
 
132
  qq : process (S_AXI_ARADDR, S_AXI_ARVALID, S_AXI_AWADDR, S_AXI_AWVALID,
133
                S_AXI_BREADY, S_AXI_RREADY, S_AXI_WDATA, S_AXI_WSTRB,
134
                S_AXI_WVALID, addr, bresp, del_bresp, del_rresp, rdata,
135
                read_wait, rresp, wb_ack_i, wb_dat_i, wb_err_i, wdata,
136
                write_wait) is
137
    variable is_read, is_write : boolean := false;
138
  begin  -- process qq
139
    -- Defaults
140
    is_read       := false;
141
    is_write      := false;
142
    wb_stb_o      <= '0';
143
    wb_addr_o     <= (others => '0');
144
    wb_dat_o      <= (others => '0');
145
    wb_we_o       <= '0';
146
    wb_cyc_o      <= '0';
147
    -- Flags handling delayed acceptance of results
148
    del_bresp_in  <= del_bresp;
149
    del_rresp_in  <= del_rresp;
150
    -- Registers storing the results
151
    bresp_in      <= bresp;
152
    rresp_in      <= rresp;
153
    rdata_in      <= rdata;
154
    wdata_in      <= wdata;
155
    read_wait_in  <= read_wait;
156
    write_wait_in <= write_wait;
157
    addr_in       <= addr;
158
    S_AXI_BVALID  <= '0';
159
    S_AXI_BRESP   <= (others => '0');
160
    S_AXI_ARREADY <= '0';
161
    S_AXI_RVALID  <= '0';
162
    S_AXI_RDATA   <= (others => '0');
163
    S_AXI_RRESP   <= (others => '0');
164
    S_AXI_AWREADY <= '0';
165
    S_AXI_WREADY  <= '0';
166
 
167
    -- Real processing
168
    -- Handling of delayed responses
169
    if del_bresp then
170
      S_AXI_BRESP  <= bresp;
171
      S_AXI_BVALID <= '1';
172
      if S_AXI_BREADY = '1' then
173
        del_bresp_in <= false;
174
      end if;
175
    elsif del_rresp then
176
      S_AXI_RRESP  <= rresp;
177
      S_AXI_RDATA  <= rdata;
178
      S_AXI_RVALID <= '1';
179
      if S_AXI_RREADY = '1' then
180
        del_rresp_in <= false;
181
      end if;
182
    -- Handling of new transactions
183
    elsif (S_AXI_AWVALID = '1' and S_AXI_WVALID = '1') or write_wait then
184
      is_write := true;
185
    elsif S_AXI_ARVALID = '1' or read_wait then
186
      is_read := true;
187
    end if;
188
    -- Set the IPbus signals
189
    if is_write then
190
      -- Check if this is a new transmission
191
      if S_AXI_AWVALID = '1' and S_AXI_WVALID = '1' and write_wait = false then
192
        -- This is a new transmission
193
        -- Check if this is a correct 32-bit write
194
        if S_AXI_WSTRB /= "1111" then
195
          -- Erroneouos write. If slave is ready to accept status, inform about it
196
          S_AXI_AWREADY <= '1';
197
          S_AXI_WREADY  <= '1';
198
          S_AXI_BRESP   <= "10";
199
          S_AXI_BVALID  <= '1';
200
          if S_AXI_BREADY = '0' then
201
            -- Prepare delayed response
202
            bresp_in     <= "10";
203
            del_bresp_in <= true;
204
          end if;
205
        else
206
          -- Correct write
207
          -- Write transaction on IPbus
208
          wb_addr_o     <= a_axi2wb(S_AXI_AWADDR);
209
          wb_dat_o      <= S_AXI_WDATA;
210
          wb_stb_o      <= '1';
211
          wb_cyc_o      <= '1';
212
          wb_we_o       <= '1';
213
          -- Store data for the next cycles
214
          addr_in       <= a_axi2wb(S_AXI_AWADDR);
215
          wdata_in      <= S_AXI_WDATA;
216
          S_AXI_AWREADY <= '1';
217
          S_AXI_WREADY  <= '1';
218
          write_wait_in <= true;
219
        end if;
220
      else
221
        -- This the next cycle of the write transmission
222
        wb_addr_o <= addr;
223
        wb_dat_o  <= wdata;
224
        wb_stb_o  <= '1';
225
        wb_cyc_o  <= '1';
226
        wb_we_o   <= '1';
227
      end if;
228
      -- Check the slave response
229
      if wb_err_i = '1' then
230
        write_wait_in <= false;
231
        S_AXI_BRESP   <= "10";
232
        S_AXI_BVALID  <= '1';
233
        if S_AXI_BREADY = '0' then
234
          -- Prepare delayed response
235
          bresp_in     <= "10";
236
          del_bresp_in <= true;
237
        end if;
238
      elsif wb_ack_i = '1' then
239
        write_wait_in <= false;
240
        S_AXI_BRESP   <= "00";
241
        S_AXI_BVALID  <= '1';
242
        if S_AXI_BREADY = '0' then
243
          -- Prepare delayed response
244
          bresp_in     <= "00";
245
          del_bresp_in <= true;
246
        end if;
247
      end if;
248
    elsif is_read then
249
      -- Read transaction on IPbus
250
      if S_AXI_ARVALID = '1' and read_wait = false then
251
        addr_in       <= a_axi2wb(S_AXI_ARADDR);
252
        wb_addr_o     <= a_axi2wb(S_AXI_ARADDR);
253
        S_AXI_ARREADY <= '1';
254
        -- Remember that we are in read
255
        read_wait_in  <= true;
256
      else
257
        wb_addr_o <= addr;
258
      end if;
259
      wb_stb_o <= '1';
260
      wb_cyc_o <= '1';
261
      wb_we_o  <= '0';
262
      -- Check the slave response
263
      if wb_err_i = '1' then
264
        S_AXI_RRESP  <= "10";
265
        S_AXI_RDATA  <= wb_dat_i;
266
        S_AXI_RVALID <= '1';
267
        read_wait_in <= false;
268
        if S_AXI_RREADY = '0' then
269
          -- Prepare delayed response
270
          rresp_in     <= "10";
271
          rdata_in     <= wb_dat_i;
272
          del_rresp_in <= true;
273
        end if;
274
      elsif wb_ack_i = '1' then
275
        S_AXI_RRESP  <= "00";
276
        S_AXI_RDATA  <= wb_dat_i;
277
        S_AXI_RVALID <= '1';
278
        read_wait_in <= false;
279
        if S_AXI_RREADY = '0' then
280
          -- Prepare delayed response
281
          rresp_in     <= "00";
282
          rdata_in     <= wb_dat_i;
283
          del_rresp_in <= true;
284
        end if;
285
      end if;
286
    end if;
287
  end process qq;
288
 
289
  process (S_AXI_ACLK) is
290
  begin  -- process
291
    if S_AXI_ACLK'event and S_AXI_ACLK = '1' then  -- rising clock edge
292
      if S_AXI_ARESETN = '0' then       -- synchronous reset (active low)
293
        del_rresp  <= false;
294
        del_bresp  <= false;
295
        rdata      <= (others => '0');
296
        wdata      <= (others => '0');
297
        rresp      <= (others => '0');
298
        bresp      <= (others => '0');
299
        addr       <= (others => '0');
300
        read_wait  <= false;
301
        write_wait <= false;
302
      else
303
        del_rresp  <= del_rresp_in;
304
        del_bresp  <= del_bresp_in;
305
        addr       <= addr_in;
306
        rdata      <= rdata_in;
307
        wdata      <= wdata_in;
308
        rresp      <= rresp_in;
309
        bresp      <= bresp_in;
310
        read_wait  <= read_wait_in;
311
        write_wait <= write_wait_in;
312
      end if;
313
    end if;
314
  end process;
315
 
316
 
317
end architecture beh;

powered by: WebSVN 2.1.0

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