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

Last change on this file was 4298, checked in by murphpo, 9 years ago

New boot_io_mux core (muxes IIC/UART between clock config core (pre-boot) and AXi peripherals (post-boot)) and eeprom core with explicit I/O/T signals for external IOBUTFs

File size: 16.0 KB
Line 
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_sda_I,
58    iic_sda_O,
59    iic_sda_T,
60
61    iic_scl_I,
62    iic_scl_O,
63    iic_scl_T,
64  // -- ADD USER PORTS ABOVE THIS LINE ---------------
65
66  // -- DO NOT EDIT BELOW THIS LINE ------------------
67  // -- Bus protocol ports, do not add to or delete
68  Bus2IP_Clk,                     // Bus to IP clock
69  Bus2IP_Resetn,                  // Bus to IP reset
70  Bus2IP_Data,                    // Bus to IP data bus
71  Bus2IP_BE,                      // Bus to IP byte enables
72  Bus2IP_RdCE,                    // Bus to IP read chip enable
73  Bus2IP_WrCE,                    // Bus to IP write chip enable
74  IP2Bus_Data,                    // IP to Bus data bus
75  IP2Bus_RdAck,                   // IP to Bus read transfer acknowledgement
76  IP2Bus_WrAck,                   // IP to Bus write transfer acknowledgement
77  IP2Bus_Error                    // IP to Bus error response
78  // -- DO NOT EDIT ABOVE THIS LINE ------------------
79); // user_logic
80
81// -- ADD USER PARAMETERS BELOW THIS LINE ------------
82// --USER parameters added here
83// -- ADD USER PARAMETERS ABOVE THIS LINE ------------
84
85// -- DO NOT EDIT BELOW THIS LINE --------------------
86// -- Bus protocol parameters, do not add to or delete
87parameter C_NUM_REG                      = 8;
88parameter C_SLV_DWIDTH                   = 32;
89// -- DO NOT EDIT ABOVE THIS LINE --------------------
90
91// -- ADD USER PORTS BELOW THIS LINE -----------------
92input  iic_sda_I;
93output iic_sda_O;
94output iic_sda_T;
95
96input  iic_scl_I;
97output iic_scl_O;
98output iic_scl_T;
99// -- ADD USER PORTS ABOVE THIS LINE -----------------
100
101// -- DO NOT EDIT BELOW THIS LINE --------------------
102// -- Bus protocol ports, do not add to or delete
103input                                     Bus2IP_Clk;
104input                                     Bus2IP_Resetn;
105input      [C_SLV_DWIDTH-1 : 0]           Bus2IP_Data;
106input      [C_SLV_DWIDTH/8-1 : 0]         Bus2IP_BE;
107input      [C_NUM_REG-1 : 0]              Bus2IP_RdCE;
108input      [C_NUM_REG-1 : 0]              Bus2IP_WrCE;
109output     [C_SLV_DWIDTH-1 : 0]           IP2Bus_Data;
110output                                    IP2Bus_RdAck;
111output                                    IP2Bus_WrAck;
112output                                    IP2Bus_Error;
113// -- DO NOT EDIT ABOVE THIS LINE --------------------
114
115//----------------------------------------------------------------------------
116// Implementation
117//----------------------------------------------------------------------------
118
119  // --USER nets declarations added here, as needed for user logic
120
121  // Nets for user logic slave model s/w accessible register example
122  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg0;
123  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg1;
124  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg2;
125  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg3;
126  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg4;
127  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg5;
128  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg6;
129  reg        [C_SLV_DWIDTH-1 : 0]           slv_reg7;
130  wire       [7 : 0]                        slv_reg_write_sel;
131  wire       [7 : 0]                        slv_reg_read_sel;
132  reg        [C_SLV_DWIDTH-1 : 0]           slv_ip2bus_data;
133  wire                                      slv_read_ack;
134  wire                                      slv_write_ack;
135  integer                                   byte_index, bit_index;
136
137  // USER logic implementation added here
138
139  // ------------------------------------------------------
140  // Example code to read/write user logic slave model s/w accessible registers
141  //
142  // Note:
143  // The example code presented here is to show you one way of reading/writing
144  // software accessible registers implemented in the user logic slave model.
145  // Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond
146  // to one software accessible register by the top level template. For example,
147  // if you have four 32 bit software accessible registers in the user logic,
148  // you are basically operating on the following memory mapped registers:
149  //
150  //    Bus2IP_WrCE/Bus2IP_RdCE   Memory Mapped Register
151  //                     "1000"   C_BASEADDR + 0x0
152  //                     "0100"   C_BASEADDR + 0x4
153  //                     "0010"   C_BASEADDR + 0x8
154  //                     "0001"   C_BASEADDR + 0xC
155  //
156  // ------------------------------------------------------
157
158  assign
159    slv_reg_write_sel = Bus2IP_WrCE[7:0],
160    slv_reg_read_sel  = Bus2IP_RdCE[7:0],
161    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],
162    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];
163
164  // implement slave model register(s)
165  always @( posedge Bus2IP_Clk )
166    begin
167
168      if ( Bus2IP_Resetn == 1'b0 )
169        begin
170          slv_reg0 <= 0;
171          slv_reg1 <= 0;
172          slv_reg2 <= 0;
173          slv_reg3 <= 0;
174          slv_reg4 <= 0;
175          slv_reg5 <= 0;
176          slv_reg6 <= 0;
177          slv_reg7 <= 0;
178        end
179      else
180        case ( slv_reg_write_sel )
181          8'b10000000 :
182            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
183              if ( Bus2IP_BE[byte_index] == 1 )
184                slv_reg0[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
185          8'b01000000 :
186            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
187              if ( Bus2IP_BE[byte_index] == 1 )
188                slv_reg1[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
189          8'b00100000 :
190            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
191              if ( Bus2IP_BE[byte_index] == 1 )
192                slv_reg2[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
193          8'b00010000 :
194            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
195              if ( Bus2IP_BE[byte_index] == 1 )
196                slv_reg3[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
197          8'b00001000 :
198            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
199              if ( Bus2IP_BE[byte_index] == 1 )
200                slv_reg4[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
201          8'b00000100 :
202            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
203              if ( Bus2IP_BE[byte_index] == 1 )
204                slv_reg5[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
205          8'b00000010 :
206            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
207              if ( Bus2IP_BE[byte_index] == 1 )
208                slv_reg6[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
209          8'b00000001 :
210            for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
211              if ( Bus2IP_BE[byte_index] == 1 )
212                slv_reg7[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
213          default : begin
214            slv_reg0 <= slv_reg0;
215            slv_reg1 <= slv_reg1;
216            slv_reg2 <= slv_reg2;
217            slv_reg3 <= slv_reg3;
218            slv_reg4 <= slv_reg4;
219            slv_reg5 <= slv_reg5;
220            slv_reg6 <= slv_reg6;
221            slv_reg7 <= slv_reg7;
222                    end
223        endcase
224
225    end // SLAVE_REG_WRITE_PROC
226
227  // implement slave model register read mux
228  always @*
229    begin 
230      case ( slv_reg_read_sel )
231        8'b10000000 : slv_ip2bus_data <= slv_reg0_rd;
232        8'b01000000 : slv_ip2bus_data <= slv_reg1;
233        8'b00100000 : slv_ip2bus_data <= slv_reg2;
234        8'b00010000 : slv_ip2bus_data <= slv_reg3_rd;
235        8'b00001000 : slv_ip2bus_data <= slv_reg4;
236        8'b00000100 : slv_ip2bus_data <= slv_reg5;
237        8'b00000010 : slv_ip2bus_data <= slv_reg6;
238        8'b00000001 : slv_ip2bus_data <= slv_reg7;
239        default : slv_ip2bus_data <= 0;
240      endcase
241
242    end // SLAVE_REG_READ_PROC
243
244  // ------------------------------------------------------------
245  // Example code to drive IP to Bus signals
246  // ------------------------------------------------------------
247
248assign IP2Bus_Data = (slv_read_ack == 1'b1) ? slv_ip2bus_data :  0 ;
249  assign IP2Bus_WrAck = slv_write_ack;
250  assign IP2Bus_RdAck = slv_read_ack;
251  assign IP2Bus_Error = 0;
252
253    /* Address map:
254        HDL is coded [MSB:LSB] = [31:0]
255        regX[31]  maps to 0x80000000 in C driver
256        regX[0] maps to 0x00000001 in C driver
257
258    0: Config/Status[31:0]:
259        [ 7: 0] clk divider (see comments below for interpretation) RW 0x000000FF
260            [8] core enable (1=enabled, 0=disabled) RW 0x00000100
261        [15: 9] reserved 0x0000FE00
262           [16] RxACK: received ACK from slave (1=received ACK) RO 0x00010000
263           [17] Busy: IIC bus busy (1 between Start and Stop events) RO 0x00020000
264           [18] AL: Arbitration lost (1 when Stop detected but not requested) RO 0x00040000
265           [19] TIP: Transfer in progress (1 during transfer) RO 0x00080000
266        [31:20] Reserved
267       
268    1: Command[31:0]: RW, self-clearing, uses local reg, not normal slv_reg1
269        [0] Start:  generate IIC start  0x01
270        [1] Stop:   generate IIC stop   0x02
271        [2] Read:   execute IIC read    0x04
272        [3] Write:  execute IIC write   0x08
273        [4] ACK:    send ACK for current transaction 0x10
274        [31:5]: Reserved
275   
276    2: Transmit[31:0]: {24'b0, txByte[7:0]} RW
277        [ 7: 0]: Tx Byte ([31]=RNW during control word writes)
278        [31: 8]: Reserved
279
280    3: Receive[31:0]: {24'b0, rxByte[7:0]} RO
281        [ 7: 0]: Rx Byte
282        [31: 8]: Reserved
283    */
284
285    reg [4:0] cmd_reg;
286    wire core_en;
287    wire [15:0] clk_div;
288    wire cmd_start, cmd_stop, cmd_read, cmd_write, cmd_ack;
289
290    wire [7:0] iic_tx_byte;
291    wire [7:0] iic_rx_byte;
292
293    wire iic_rx_ack;
294    wire iic_bus_busy;
295    wire iic_al;
296    wire iic_done;
297    wire iic_tip;
298   
299    wire slv_reg1_WE;
300    assign slv_reg1_WE = Bus2IP_WrCE[6]; //WrCE/RdCE[7:0] map to slv_reg[0:7]
301
302    //Custom command register logic, implements self-clearing bits
303    always @( posedge Bus2IP_Clk )
304    begin
305        if ( Bus2IP_Resetn == 1'b0 )
306            cmd_reg <= 5'b0;
307        else if(slv_reg1_WE == 1'b1)
308            cmd_reg[4:0] <= Bus2IP_Data[4:0];
309        else if(iic_done | iic_al)
310        begin
311             //Clear start, stop, read, write bits on transfer completion or arbitration loss
312//          cmd_reg[4:1] <= 4'b0;
313//          cmd_reg[0] <= cmd_reg[0];
314            cmd_reg[3:0] <= 4'b0;
315            cmd_reg[4] <= cmd_reg[4];
316        end
317        else
318            cmd_reg[4:0] <= cmd_reg[4:0];
319    end
320   
321    assign cmd_start = cmd_reg[0]; //0x01 from driver
322    assign cmd_stop  = cmd_reg[1]; //0x02
323    assign cmd_read  = cmd_reg[2]; //0x04
324    assign cmd_write = cmd_reg[3]; //0x08
325    assign cmd_ack   = cmd_reg[4]; //0x10
326
327    assign iic_tip = (cmd_read | cmd_write); //register bits self-clear on transfer completion
328
329   
330    //Construct 32-bit vectors for read access to mixed RW/RO registers
331    wire [31:0] slv_reg0_rd;
332    wire [31:0] slv_reg3_rd;
333    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]};
334    assign slv_reg3_rd = {24'b0, iic_rx_byte[7:0]};
335   
336
337    //IIC master divides down master clock to generate SCL
338    // SCL rate is (sys_clk / (5*clk_div[0:15]))
339    // For 200MHz sys_clk and 100kHz SCL, clk_div = 400 = 0x190
340    // Interpret user-provided clock divider as bits[6:13] of clk_div
341    assign clk_div[15:0] = {6'b0, slv_reg0[7:0], 2'b0};
342    assign core_en = slv_reg0[8];
343
344
345    assign iic_tx_byte = slv_reg2[7:0];
346
347    wire sda_pad_i, sda_pad_o, sda_pad_oe;
348    wire scl_pad_i, scl_pad_o, scl_pad_oe;
349
350    i2c_master_byte_ctrl byte_controller (
351        .clk      ( Bus2IP_Clk ), //master clock
352        .rst      ( ~Bus2IP_Resetn ), //synchronous reset, active high
353        .nReset   ( 1'b1 ), //asynchronous reset, acvtive low
354        .ena      ( core_en ), //core enable, active high
355        .clk_cnt  ( clk_div ), //master-to-iic clock divider
356        .start    ( cmd_start ), //send iic start
357        .stop     ( cmd_stop ), //send iic stop
358        .read     ( cmd_read ), //perform iic read
359        .write    ( cmd_write ), //perform iic write
360        .ack_in   ( cmd_ack ), //send iic ack
361        .din      ( iic_tx_byte ), //byte to send
362        .cmd_ack  ( iic_done ), //xfer is done
363        .ack_out  ( iic_rx_ack ), //ack from slave
364        .dout     ( iic_rx_byte ), //byte read from slave
365        .i2c_busy ( iic_bus_busy ),
366        .i2c_al   ( iic_al ), //arbitration lost output
367        .scl_i    ( iic_scl_I ), //iic scl input (pad -> logic)
368        .scl_o    ( iic_scl_O ), //iic scl output (logic -> pad)
369        .scl_oen  ( iic_scl_T ), //iic scl output enable (0=scl is logic-driven output)
370        .sda_i    ( iic_sda_I ), //iic sda input (pad -> logic)
371        .sda_o    ( iic_sda_O ), //iic sda output (logic -> pad)
372        .sda_oen  ( iic_sda_T ) //iic sda output enable (0=sda is logic-driven output)
373    );
374   
375endmodule
Note: See TracBrowser for help on using the repository browser.