]> rtime.felk.cvut.cz Git - fpga/zynq/canbench-sw.git/blob - system/ip/sja1000_1.0/hdl/can_ifc_axi.v
bitstream file renamed
[fpga/zynq/canbench-sw.git] / system / ip / sja1000_1.0 / hdl / can_ifc_axi.v
1 //////////////////////////////////////////////////////////////////////
2 ////                                                              ////
3 ////  can_top.v                                                   ////
4 ////                                                              ////
5 ////                                                              ////
6 ////  This file is part of the CAN Protocol Controller            ////
7 ////  http://www.opencores.org/projects/can/                      ////
8 ////                                                              ////
9 ////                                                              ////
10 ////  Author(s):                                                  ////
11 ////       Igor Mohor                                             ////
12 ////       igorm@opencores.org                                    ////
13 ////                                                              ////
14 ////                                                              ////
15 ////  All additional information is available in the README.txt   ////
16 ////  file.                                                       ////
17 ////                                                              ////
18 //////////////////////////////////////////////////////////////////////
19 ////                                                              ////
20 //// Copyright (C) 2002, 2003, 2004 Authors                       ////
21 ////                                                              ////
22 //// This source file may be used and distributed without         ////
23 //// restriction provided that this copyright statement is not    ////
24 //// removed from the file and that any derivative work contains  ////
25 //// the original copyright notice and the associated disclaimer. ////
26 ////                                                              ////
27 //// This source file is free software; you can redistribute it   ////
28 //// and/or modify it under the terms of the GNU Lesser General   ////
29 //// Public License as published by the Free Software Foundation; ////
30 //// either version 2.1 of the License, or (at your option) any   ////
31 //// later version.                                               ////
32 ////                                                              ////
33 //// This source is distributed in the hope that it will be       ////
34 //// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
35 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
36 //// PURPOSE.  See the GNU Lesser General Public License for more ////
37 //// details.                                                     ////
38 ////                                                              ////
39 //// You should have received a copy of the GNU Lesser General    ////
40 //// Public License along with this source; if not, download it   ////
41 //// from http://www.opencores.org/lgpl.shtml                     ////
42 ////                                                              ////
43 //// The CAN protocol is developed by Robert Bosch GmbH and       ////
44 //// protected by patents. Anybody who wants to implement this    ////
45 //// CAN IP core on silicon has to obtain a CAN protocol license  ////
46 //// from Bosch.                                                  ////
47 ////                                                              ////
48 //////////////////////////////////////////////////////////////////////
49
50 // synopsys translate_off
51 `include "timescale.v"
52 // synopsys translate_on
53 `include "can_defines.v"
54
55 module can_ifc_async
56 (
57   input wire clk_i,
58   input wire rstn_i,
59   output wire reg_cs_o,
60
61   input wire req_i,
62   output wire ack_o
63 );
64   reg oreq;
65   reg ack;
66
67   assign ack_o = ack;
68   assign reg_cs_o = oreq != req_i;
69
70   always @(posedge clk_i or negedge rstn_i)
71   begin
72     if (~rstn_i)
73     begin
74       ack <= 1'b0;
75       oreq <= 1'b0;
76     end else begin
77       if (oreq != req_i)
78       begin
79         // we is already set from axi side and is stable
80         // data_in is already set from axi side and is stable
81         // data_out is set from reg in this cycle
82         ack <= ~ack;
83         oreq <= ~oreq;
84       end
85     end
86   end
87 endmodule
88
89 module can_ifc_axi
90 #(
91   // Width of S_AXI data bus
92   parameter integer C_S_AXI_DATA_WIDTH = 32,
93   // Width of S_AXI address bus
94   parameter integer C_S_AXI_ADDR_WIDTH = 8
95 )
96 (
97   input wire clk_i,
98   output wire reg_rst_o,
99   output wire reg_cs_o,
100   output wire reg_we_o,
101   output wire [7:0] reg_addr_o,
102   output wire [7:0] reg_data_in_o,
103   input wire  [7:0] reg_data_out_i,
104
105         input wire  S_AXI_ACLK,
106         input wire  S_AXI_ARESETN,
107
108         input wire  [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
109         input wire  [2:0]                      S_AXI_AWPROT,
110         input wire                             S_AXI_AWVALID,
111         output reg                             S_AXI_AWREADY,
112
113         input wire [C_S_AXI_DATA_WIDTH-1 : 0]     S_AXI_WDATA,
114         input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
115         input wire                                S_AXI_WVALID,
116         output reg                                S_AXI_WREADY,
117
118         output reg [1:0]                       S_AXI_BRESP,
119         output reg                             S_AXI_BVALID,
120         input wire                             S_AXI_BREADY,
121
122         input wire  [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
123         input wire  [2:0]                      S_AXI_ARPROT,
124         input wire                             S_AXI_ARVALID,
125         output reg                             S_AXI_ARREADY,
126
127         output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, // TODO: reg
128         output reg  [1:0]                      S_AXI_RRESP,
129         output reg                             S_AXI_RVALID,
130         input wire                             S_AXI_RREADY
131 );
132
133 parameter Tp = 1;
134 /*
135 input        clk_i;
136 output       reg_rst_o;
137 output       reg_cs_o;
138 output       reg_we_o;
139 output [7:0] reg_data_in_o;
140 input  [7:0] reg_data_out_i;
141 */
142
143
144     reg write_pending;
145     reg write_active;
146     reg read_pending;
147     reg read_active;
148
149     reg  [1:0] ready_read_hist;
150     reg  [1:0] ready_write_hist;
151     wire ready_read_edge;
152     wire ready_write_edge;
153     assign ready_read_edge = ready_read_hist[0] ^ ready_read_hist[1];
154     assign ready_write_edge = ready_write_hist[0] ^ ready_write_hist[1];
155     
156     wire read_finished;
157     wire write_finished;
158     
159     reg read_active_edge;
160     reg write_active_edge;
161
162     reg req;
163     reg oack;
164     wire ack_i;
165
166     assign read_finished = S_AXI_RVALID;
167     assign write_finished = S_AXI_BVALID;
168
169     // read/write arbitration
170     always @ (posedge S_AXI_ACLK or negedge S_AXI_RST)
171     begin
172       if (~S_AXI_RST)
173       begin
174         write_pending <= 1'b0;
175         write_active <= 1'b0;
176         read_pending <= 1'b0;
177         read_active <= 1'b0;
178         ready_read_hist <= 2'b00;
179         ready_write_hist <= 2'b00;
180       end
181       else
182       begin
183         ready_read_hist <= {ready_read_hist[0], S_AXI_ARVALID};
184         ready_write_hist <= {ready_write_hist[0], S_AXI_AWVALID & S_AXI_WVALID /*& (S_AXI_WSTRB == 4'b1111)*/};
185
186         /*
187         if(S_AXI_AWVALID & S_AXI_WVALID & (S_AXI_WSTRB != 4'b1111))
188         begin
189           S_AXI_BVALID <= 1;
190           S_AXI_BRESP <= ...;
191         end
192         */
193
194         if (write_active_edge)
195           write_active_edge = 0;
196         if (read_active_edge)
197           read_active_edge = 0;
198
199         if (ready_write_edge)
200         begin
201           if (read_active & ~read_finished)
202             write_pending <= 1;
203           else
204           begin
205             write_active <= 1;
206             write_active_edge = 1;
207           end
208         end
209
210         if (ready_read_edge)
211         begin
212           if (write_active & ~write_finished)
213             read_pending <= 1;
214           else
215           begin
216             read_active <= 1;
217             read_active_edge = 1;
218           end
219         end
220
221         // read finished in previous cycle
222         if (read_finished)
223         begin
224           read_active <= 1'b0;
225           if (write_pending)
226           begin
227             write_active <= 1;
228             write_pending <= 0;
229           end
230         end
231
232         // write finished in previous cycle
233         if (write_finished)
234         begin
235           write_active <= 1'b0;
236           if (read_pending)
237           begin
238             read_active <= 1;
239             read_pending <= 0;
240           end
241         end
242       end
243     end
244
245     //assign reg_addr_o <= write ? axi_waddr : axi_raddr;
246     // assign reg_addr_o - asynchronous, synchronized by protocols expectations
247     // should not synthesise any regs or latches
248     assign reg_addr_o = write_active ? S_AXI_AWADDR :
249                         read_active  ? S_AXI_ARADDR :
250                         8'bxxxxxxxx;
251
252     /*
253     // latch read response data
254     always @(posedge S_AXI_ACLK)
255     begin
256       if (read_active)
257         latched_data <= reg_data_out_i;
258     end
259     */
260
261     always @(negedge S_AXI_RST or posedge S_AXI_ACLK)
262     begin
263       if (~S_AXI_RST)
264       begin
265         oack <= 1'b0;
266         //S_AXI_RDATA <=#C_S_AXI_DATA_WIDTH 0;
267         S_AXI_BRESP <= 0;
268         S_AXI_BVALID <= 1'b0;
269         S_AXI_WREADY <= 1'b0;
270         S_AXI_AWREADY <= 1'b0;
271       end else
272       begin
273         // no synchronization necessary
274         if (read_active_edge | write_active_edge)
275           req <= ~req;
276         if (oack != ack_i)
277         begin
278           if (read_active)
279           begin
280             //S_AXI_RDATA <= reg_data_out_i; // TODO: should be allright, the address is stable ...
281             // read_active will be deasserted after asserting S_AXI_RVALID, so this will execute only 2x
282             S_AXI_RVALID <= ~S_AXI_RVALID;
283             S_AXI_ARREADY <= ~S_AXI_ARREADY;
284           end else if (write_active)
285           begin
286             S_AXI_BRESP <= 2'b00; // TODO: value?
287             // write_active will be deasserted after asserting S_AXI_RVALID, so this will execute only 2x
288             S_AXI_BVALID <= ~S_AXI_BVALID;
289             S_AXI_WREADY <= ~S_AXI_WREADY;
290             S_AXI_AWREADY <= ~S_AXI_AWREADY;
291           end
292           oack <= ~oack;
293         end
294       end
295      end
296
297   assign reg_rst_o       = ~S_AXI_RST;
298   assign reg_we_o        = write_active;
299   assign reg_addr_o      = S_AXI_AWADDR; // TODO: latch?
300   assign reg_data_in_o   = S_AXI_WDATA;
301   assign S_AXI_RDATA     = reg_data_out_i; // TODO: latch?
302
303   can_ifc_async CAN_IFC_ASYNC
304   (
305     .clk_i(clk_i),
306     .rstn_i(S_AXI_RST),
307     .reg_cs_o(reg_cs_o),
308     .req_i(req),
309     .ack_o(ack)
310   );
311 endmodule