source: PlatformSupport/CustomPeripherals/pcores/w3_iic_eeprom_axi_v1_00_b/hdl/verilog/user_logic.v

Last change on this file was 1927, checked in by murphpo, 11 years ago

AXI versions of WARP v3 support cores

File size: 16.2 KB
RevLine 
[1927]1//----------------------------------------------------------------------------
2// user_logic.v - module
3//----------------------------------------------------------------------------
4//
5// ***************************************************************************
6// ** Copyright (c) 1995-2012 Xilinx, Inc.  All rights reserved.            **
7// **                                                                       **
8// ** Xilinx, Inc.                                                          **
9// ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"         **
10// ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND       **
11// ** SOLUTIONS FOR XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE,        **
12// ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,        **
13// ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION           **
14// ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,     **
15// ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE      **
16// ** FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY              **
17// ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE               **
18// ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR        **
19// ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF       **
20// ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS       **
21// ** FOR A PARTICULAR PURPOSE.                                             **
22// **                                                                       **
23// ***************************************************************************
24//
25//----------------------------------------------------------------------------
26// Filename:          user_logic.v
27// Version:           1.00.b
28// Description:       User logic module.
29// Date:              Sat Feb 23 20:58:52 2013 (by Create and Import Peripheral Wizard)
30// Verilog Standard:  Verilog-2001
31//----------------------------------------------------------------------------
32// Naming Conventions:
33//   active low signals:                    "*_n"
34//   clock signals:                         "clk", "clk_div#", "clk_#x"
35//   reset signals:                         "rst", "rst_n"
36//   generics:                              "C_*"
37//   user defined types:                    "*_TYPE"
38//   state machine next state:              "*_ns"
39//   state machine current state:           "*_cs"
40//   combinatorial signals:                 "*_com"
41//   pipelined or register delay signals:   "*_d#"
42//   counter signals:                       "*cnt*"
43//   clock enable signals:                  "*_ce"
44//   internal version of output port:       "*_i"
45//   device pins:                           "*_pin"
46//   ports:                                 "- Names begin with Uppercase"
47//   processes:                             "*_PROCESS"
48//   component instantiations:              "<ENTITY_>I_<#|FUNC>"
49//----------------------------------------------------------------------------
50
51`uselib lib=unisims_ver
52`uselib lib=proc_common_v3_00_a
53
54module user_logic
55(
56  // -- ADD USER PORTS BELOW THIS LINE ---------------
57    iic_scl,
58    iic_sda,
59  // -- ADD USER PORTS ABOVE THIS LINE ---------------
60
61  // -- DO NOT EDIT BELOW THIS LINE ------------------
62  // -- Bus protocol ports, do not add to or delete
63  Bus2IP_Clk,                     // Bus to IP clock
64  Bus2IP_Resetn,                  // Bus to IP reset
65  Bus2IP_Data,                    // Bus to IP data bus
66  Bus2IP_BE,                      // Bus to IP byte enables
67  Bus2IP_RdCE,                    // Bus to IP read chip enable
68  Bus2IP_WrCE,                    // Bus to IP write chip enable
69  IP2Bus_Data,                    // IP to Bus data bus
70  IP2Bus_RdAck,                   // IP to Bus read transfer acknowledgement
71  IP2Bus_WrAck,                   // IP to Bus write transfer acknowledgement
72  IP2Bus_Error                    // IP to Bus error response
73  // -- DO NOT EDIT ABOVE THIS LINE ------------------
74); // user_logic
75
76// -- ADD USER PARAMETERS BELOW THIS LINE ------------
77// --USER parameters added here
78// -- ADD USER PARAMETERS ABOVE THIS LINE ------------
79
80// -- DO NOT EDIT BELOW THIS LINE --------------------
81// -- Bus protocol parameters, do not add to or delete
82parameter C_NUM_REG                      = 8;
83parameter C_SLV_DWIDTH                   = 32;
84// -- DO NOT EDIT ABOVE THIS LINE --------------------
85
86// -- ADD USER PORTS BELOW THIS LINE -----------------
87inout iic_scl;
88inout iic_sda;
89// -- ADD USER PORTS ABOVE THIS LINE -----------------
90
91// -- DO NOT EDIT BELOW THIS LINE --------------------
92// -- Bus protocol ports, do not add to or delete
93input                                     Bus2IP_Clk;
94input                                     Bus2IP_Resetn;
95input      [C_SLV_DWIDTH-1 : 0]           Bus2IP_Data;
96input      [C_SLV_DWIDTH/8-1 : 0]         Bus2IP_BE;
97input      [C_NUM_REG-1 : 0]              Bus2IP_RdCE;
98input      [C_NUM_REG-1 : 0]              Bus2IP_WrCE;
99output     [C_SLV_DWIDTH-1 : 0]           IP2Bus_Data;
100output                                    IP2Bus_RdAck;
101output                                    IP2Bus_WrAck;
102output                                    IP2Bus_Error;
103// -- DO NOT EDIT ABOVE THIS LINE --------------------
104
105//----------------------------------------------------------------------------
106// Implementation
107//----------------------------------------------------------------------------
108
109  // --USER nets declarations added here, as needed for user logic
110
111  // Nets for user logic slave model s/w accessible register example
112  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg0;
113  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg1;
114  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg2;
115  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg3;
116  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg4;
117  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg5;
118  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg6;
119  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg7;
120  wire       [7 : 0]                        slv_reg_write_sel;
121  wire       [7 : 0]                        slv_reg_read_sel;
122  reg        [C_SLV_DWIDTH-1 : 0]           slv_ip2bus_data;
123  wire                                      slv_read_ack;
124  wire                                      slv_write_ack;
125  integer                                   byte_index, bit_index;
126
127  // USER logic implementation added here
128
129  // ------------------------------------------------------
130  // Example code to read/write user logic slave model s/w accessible registers
131  //
132  // Note:
133  // The example code presented here is to show you one way of reading/writing
134  // software accessible registers implemented in the user logic slave model.
135  // Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond
136  // to one software accessible register by the top level template. For example,
137  // if you have four 32 bit software accessible registers in the user logic,
138  // you are basically operating on the following memory mapped registers:
139  //
140  //    Bus2IP_WrCE/Bus2IP_RdCE   Memory Mapped Register
141  //                     "1000"   C_BASEADDR + 0x0
142  //                     "0100"   C_BASEADDR + 0x4
143  //                     "0010"   C_BASEADDR + 0x8
144  //                     "0001"   C_BASEADDR + 0xC
145  //
146  // ------------------------------------------------------
147
148  assign
149    slv_reg_write_sel = Bus2IP_WrCE[7:0],
150    slv_reg_read_sel  = Bus2IP_RdCE[7:0],
151    slv_write_ack     = Bus2IP_WrCE[0] || Bus2IP_WrCE[1] || Bus2IP_WrCE[2] || Bus2IP_WrCE[3] || Bus2IP_WrCE[4] || Bus2IP_WrCE[5] || Bus2IP_WrCE[6] || Bus2IP_WrCE[7],
152    slv_read_ack      = Bus2IP_RdCE[0] || Bus2IP_RdCE[1] || Bus2IP_RdCE[2] || Bus2IP_RdCE[3] || Bus2IP_RdCE[4] || Bus2IP_RdCE[5] || Bus2IP_RdCE[6] || Bus2IP_RdCE[7];
153
154  // implement slave model register(s)
155  always @( posedge Bus2IP_Clk )
156    begin
157
158      if ( Bus2IP_Resetn == 1'b0 )
159        begin
160          slv_reg0 <= 0;
161          slv_reg1 <= 0;
162          slv_reg2 <= 0;
163          slv_reg3 <= 0;
164          slv_reg4 <= 0;
165          slv_reg5 <= 0;
166          slv_reg6 <= 0;
167          slv_reg7 <= 0;
168        end
169      else
170        case ( slv_reg_write_sel )
171          8'b10000000 :
172            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
173              if ( Bus2IP_BE[byte_index] == 1 )
174                slv_reg0[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
175          8'b01000000 :
176            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
177              if ( Bus2IP_BE[byte_index] == 1 )
178                slv_reg1[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
179          8'b00100000 :
180            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
181              if ( Bus2IP_BE[byte_index] == 1 )
182                slv_reg2[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
183          8'b00010000 :
184            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
185              if ( Bus2IP_BE[byte_index] == 1 )
186                slv_reg3[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
187          8'b00001000 :
188            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
189              if ( Bus2IP_BE[byte_index] == 1 )
190                slv_reg4[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
191          8'b00000100 :
192            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
193              if ( Bus2IP_BE[byte_index] == 1 )
194                slv_reg5[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
195          8'b00000010 :
196            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
197              if ( Bus2IP_BE[byte_index] == 1 )
198                slv_reg6[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
199          8'b00000001 :
200            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
201              if ( Bus2IP_BE[byte_index] == 1 )
202                slv_reg7[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
203          default : begin
204            slv_reg0 <= slv_reg0;
205            slv_reg1 <= slv_reg1;
206            slv_reg2 <= slv_reg2;
207            slv_reg3 <= slv_reg3;
208            slv_reg4 <= slv_reg4;
209            slv_reg5 <= slv_reg5;
210            slv_reg6 <= slv_reg6;
211            slv_reg7 <= slv_reg7;
212                    end
213        endcase
214
215    end // SLAVE_REG_WRITE_PROC
216
217  // implement slave model register read mux
218  always @*
219    begin 
220      case ( slv_reg_read_sel )
221        8'b10000000 : slv_ip2bus_data <= slv_reg0_rd;
222        8'b01000000 : slv_ip2bus_data <= slv_reg1;
223        8'b00100000 : slv_ip2bus_data <= slv_reg2;
224        8'b00010000 : slv_ip2bus_data <= slv_reg3_rd;
225        8'b00001000 : slv_ip2bus_data <= slv_reg4;
226        8'b00000100 : slv_ip2bus_data <= slv_reg5;
227        8'b00000010 : slv_ip2bus_data <= slv_reg6;
228        8'b00000001 : slv_ip2bus_data <= slv_reg7;
229        default : slv_ip2bus_data <= 0;
230      endcase
231
232    end // SLAVE_REG_READ_PROC
233
234  // ------------------------------------------------------------
235  // Example code to drive IP to Bus signals
236  // ------------------------------------------------------------
237
238assign IP2Bus_Data = (slv_read_ack == 1'b1) ? slv_ip2bus_data :  0 ;
239  assign IP2Bus_WrAck = slv_write_ack;
240  assign IP2Bus_RdAck = slv_read_ack;
241  assign IP2Bus_Error = 0;
242
243    /* Address map:
244        HDL is coded [MSB:LSB] = [31:0]
245        regX[31]  maps to 0x80000000 in C driver
246        regX[0] maps to 0x00000001 in C driver
247
248    0: Config/Status[31:0]:
249        [ 7: 0] clk divider (see comments below for interpretation) RW 0x000000FF
250            [8] core enable (1=enabled, 0=disabled) RW 0x00000100
251        [15: 9] reserved 0x0000FE00
252           [16] RxACK: received ACK from slave (1=received ACK) RO 0x00010000
253           [17] Busy: IIC bus busy (1 between Start and Stop events) RO 0x00020000
254           [18] AL: Arbitration lost (1 when Stop detected but not requested) RO 0x00040000
255           [19] TIP: Transfer in progress (1 during transfer) RO 0x00080000
256        [31:20] Reserved
257       
258    1: Command[31:0]: RW, self-clearing, uses local reg, not normal slv_reg1
259        [0] Start:  generate IIC start  0x01
260        [1] Stop:   generate IIC stop   0x02
261        [2] Read:   execute IIC read    0x04
262        [3] Write:  execute IIC write   0x08
263        [4] ACK:    send ACK for current transaction 0x10
264        [31:5]: Reserved
265   
266    2: Transmit[31:0]: {24'b0, txByte[7:0]} RW
267        [ 7: 0]: Tx Byte ([31]=RNW during control word writes)
268        [31: 8]: Reserved
269
270    3: Receive[31:0]: {24'b0, rxByte[7:0]} RO
271        [ 7: 0]: Rx Byte
272        [31: 8]: Reserved
273    */
274
275    reg [4:0] cmd_reg;
276    wire core_en;
277    wire [15:0] clk_div;
278    wire cmd_start, cmd_stop, cmd_read, cmd_write, cmd_ack;
279
280    wire [7:0] iic_tx_byte;
281    wire [7:0] iic_rx_byte;
282
283    wire iic_rx_ack;
284    wire iic_bus_busy;
285    wire iic_al;
286    wire iic_done;
287    wire iic_tip;
288   
289    wire slv_reg1_WE;
290    assign slv_reg1_WE = Bus2IP_WrCE[6]; //WrCE/RdCE[7:0] map to slv_reg[0:7]
291
292    //Custom command register logic, implements self-clearing bits
293    always @( posedge Bus2IP_Clk )
294    begin
295        if ( Bus2IP_Resetn == 1'b0 )
296            cmd_reg <= 5'b0;
297        else if(slv_reg1_WE == 1'b1)
298            cmd_reg[4:0] <= Bus2IP_Data[4:0];
299        else if(iic_done | iic_al)
300        begin
301             //Clear start, stop, read, write bits on transfer completion or arbitration loss
302//          cmd_reg[4:1] <= 4'b0;
303//          cmd_reg[0] <= cmd_reg[0];
304            cmd_reg[3:0] <= 4'b0;
305            cmd_reg[4] <= cmd_reg[4];
306        end
307        else
308            cmd_reg[4:0] <= cmd_reg[4:0];
309    end
310   
311    assign cmd_start = cmd_reg[0]; //0x01 from driver
312    assign cmd_stop  = cmd_reg[1]; //0x02
313    assign cmd_read  = cmd_reg[2]; //0x04
314    assign cmd_write = cmd_reg[3]; //0x08
315    assign cmd_ack   = cmd_reg[4]; //0x10
316
317    assign iic_tip = (cmd_read | cmd_write); //register bits self-clear on transfer completion
318
319   
320    //Construct 32-bit vectors for read access to mixed RW/RO registers
321    wire [31:0] slv_reg0_rd;
322    wire [31:0] slv_reg3_rd;
323    assign slv_reg0_rd = {12'b0, iic_tip, iic_al, iic_bus_busy, iic_rx_ack, 7'b0, slv_reg0[8], slv_reg0[7:0]};
324    assign slv_reg3_rd = {24'b0, iic_rx_byte[7:0]};
325   
326
327    //IIC master divides down master clock to generate SCL
328    // SCL rate is (sys_clk / (5*clk_div[0:15]))
329    // For 200MHz sys_clk and 100kHz SCL, clk_div = 400 = 0x190
330    // Interpret user-provided clock divider as bits[6:13] of clk_div
331    assign clk_div[15:0] = {6'b0, slv_reg0[7:0], 2'b0};
332    assign core_en = slv_reg0[8];
333
334
335    assign iic_tx_byte = slv_reg2[7:0];
336
337    wire sda_pad_i, sda_pad_o, sda_pad_oe;
338    wire scl_pad_i, scl_pad_o, scl_pad_oe;
339
340    IOBUF IOBUF_sda (
341        .IO(iic_sda), //Connected to actual FPGA pin
342        .I(sda_pad_o), //Logic-> Pad, input to OBUFT
343        .O(sda_pad_i), //Pad-> Logic, output of IBUF
344        .T(sda_pad_oe)
345    );
346
347    IOBUF IOBUF_scl (
348        .IO(iic_scl), //Connected to actual FPGA pin
349        .I(scl_pad_o), //Logic-> Pad, input to OBUFT
350        .O(scl_pad_i), //Pad-> Logic, output of IBUF
351        .T(scl_pad_oe)
352    );
353
354    i2c_master_byte_ctrl byte_controller (
355        .clk      ( Bus2IP_Clk ), //master clock
356        .rst      ( ~Bus2IP_Resetn ), //synchronous reset, active high
357        .nReset   ( 1'b1 ), //asynchronous reset, acvtive low
358        .ena      ( core_en ), //core enable, active high
359        .clk_cnt  ( clk_div ), //master-to-iic clock divider
360        .start    ( cmd_start ), //send iic start
361        .stop     ( cmd_stop ), //send iic stop
362        .read     ( cmd_read ), //perform iic read
363        .write    ( cmd_write ), //perform iic write
364        .ack_in   ( cmd_ack ), //send iic ack
365        .din      ( iic_tx_byte ), //byte to send
366        .cmd_ack  ( iic_done ), //xfer is done
367        .ack_out  ( iic_rx_ack ), //ack from slave
368        .dout     ( iic_rx_byte ), //byte read from slave
369        .i2c_busy ( iic_bus_busy ),
370        .i2c_al   ( iic_al ), //arbitration lost output
371        .scl_i    ( scl_pad_i ), //iic scl input (pad -> logic)
372        .scl_o    ( scl_pad_o ), //iic scl output (logic -> pad)
373        .scl_oen  ( scl_pad_oe ), //iic scl output enable (0=scl is logic-driven output)
374        .sda_i    ( sda_pad_i ), //iic sda input (pad -> logic)
375        .sda_o    ( sda_pad_o ), //iic sda output (logic -> pad)
376        .sda_oen  ( sda_pad_oe ) //iic sda output enable (0=sda is logic-driven output)
377    );
378   
379endmodule
Note: See TracBrowser for help on using the repository browser.