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

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

Minor tweaks to EEPROM controller HDL/MPD

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