//---------------------------------------------------------------------------- // user_logic.v - module //---------------------------------------------------------------------------- // // *************************************************************************** // ** Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. ** // ** ** // ** Xilinx, Inc. ** // ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" ** // ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND ** // ** SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, ** // ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, ** // ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION ** // ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, ** // ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE ** // ** FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY ** // ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE ** // ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR ** // ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF ** // ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ** // ** FOR A PARTICULAR PURPOSE. ** // ** ** // *************************************************************************** // //---------------------------------------------------------------------------- // Filename: user_logic.v // Version: 1.00.b // Description: User logic module. // Date: Sat Feb 23 20:58:52 2013 (by Create and Import Peripheral Wizard) // Verilog Standard: Verilog-2001 //---------------------------------------------------------------------------- // Naming Conventions: // active low signals: "*_n" // clock signals: "clk", "clk_div#", "clk_#x" // reset signals: "rst", "rst_n" // generics: "C_*" // user defined types: "*_TYPE" // state machine next state: "*_ns" // state machine current state: "*_cs" // combinatorial signals: "*_com" // pipelined or register delay signals: "*_d#" // counter signals: "*cnt*" // clock enable signals: "*_ce" // internal version of output port: "*_i" // device pins: "*_pin" // ports: "- Names begin with Uppercase" // processes: "*_PROCESS" // component instantiations: "I_<#|FUNC>" //---------------------------------------------------------------------------- `uselib lib=unisims_ver `uselib lib=proc_common_v3_00_a module user_logic ( // -- ADD USER PORTS BELOW THIS LINE --------------- iic_sda_I, iic_sda_O, iic_sda_T, iic_scl_I, iic_scl_O, iic_scl_T, // -- ADD USER PORTS ABOVE THIS LINE --------------- // -- DO NOT EDIT BELOW THIS LINE ------------------ // -- Bus protocol ports, do not add to or delete Bus2IP_Clk, // Bus to IP clock Bus2IP_Resetn, // Bus to IP reset Bus2IP_Data, // Bus to IP data bus Bus2IP_BE, // Bus to IP byte enables Bus2IP_RdCE, // Bus to IP read chip enable Bus2IP_WrCE, // Bus to IP write chip enable IP2Bus_Data, // IP to Bus data bus IP2Bus_RdAck, // IP to Bus read transfer acknowledgement IP2Bus_WrAck, // IP to Bus write transfer acknowledgement IP2Bus_Error // IP to Bus error response // -- DO NOT EDIT ABOVE THIS LINE ------------------ ); // user_logic // -- ADD USER PARAMETERS BELOW THIS LINE ------------ // --USER parameters added here // -- ADD USER PARAMETERS ABOVE THIS LINE ------------ // -- DO NOT EDIT BELOW THIS LINE -------------------- // -- Bus protocol parameters, do not add to or delete parameter C_NUM_REG = 16; parameter C_SLV_DWIDTH = 32; // -- DO NOT EDIT ABOVE THIS LINE -------------------- // -- ADD USER PORTS BELOW THIS LINE ----------------- input iic_sda_I; output iic_sda_O; output iic_sda_T; input iic_scl_I; output iic_scl_O; output iic_scl_T; // -- ADD USER PORTS ABOVE THIS LINE ----------------- // -- DO NOT EDIT BELOW THIS LINE -------------------- // -- Bus protocol ports, do not add to or delete input Bus2IP_Clk; input Bus2IP_Resetn; input [C_SLV_DWIDTH-1 : 0] Bus2IP_Data; input [C_SLV_DWIDTH/8-1 : 0] Bus2IP_BE; input [C_NUM_REG-1 : 0] Bus2IP_RdCE; input [C_NUM_REG-1 : 0] Bus2IP_WrCE; output [C_SLV_DWIDTH-1 : 0] IP2Bus_Data; output IP2Bus_RdAck; output IP2Bus_WrAck; output IP2Bus_Error; // -- DO NOT EDIT ABOVE THIS LINE -------------------- //---------------------------------------------------------------------------- // Implementation //---------------------------------------------------------------------------- // --USER nets declarations added here, as needed for user logic // Nets for user logic slave model s/w accessible register example reg [C_SLV_DWIDTH-1 : 0] slv_reg00; reg [C_SLV_DWIDTH-1 : 0] slv_reg01; reg [C_SLV_DWIDTH-1 : 0] slv_reg02; reg [C_SLV_DWIDTH-1 : 0] slv_reg03; reg [C_SLV_DWIDTH-1 : 0] slv_reg04; reg [C_SLV_DWIDTH-1 : 0] slv_reg05; reg [C_SLV_DWIDTH-1 : 0] slv_reg06; reg [C_SLV_DWIDTH-1 : 0] slv_reg07; reg [C_SLV_DWIDTH-1 : 0] slv_reg08; reg [C_SLV_DWIDTH-1 : 0] slv_reg09; reg [C_SLV_DWIDTH-1 : 0] slv_reg10; reg [C_SLV_DWIDTH-1 : 0] slv_reg11; reg [C_SLV_DWIDTH-1 : 0] slv_reg12; reg [C_SLV_DWIDTH-1 : 0] slv_reg13; reg [C_SLV_DWIDTH-1 : 0] slv_reg14; reg [C_SLV_DWIDTH-1 : 0] slv_reg15; wire [15: 0] slv_reg_write_sel; wire [15: 0] slv_reg_read_sel; reg [C_SLV_DWIDTH-1 : 0] slv_ip2bus_data; wire slv_read_ack; wire slv_write_ack; integer byte_index, bit_index; // USER logic implementation added here // ------------------------------------------------------ // Example code to read/write user logic slave model s/w accessible registers // // Note: // The example code presented here is to show you one way of reading/writing // software accessible registers implemented in the user logic slave model. // Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond // to one software accessible register by the top level template. For example, // if you have four 32 bit software accessible registers in the user logic, // you are basically operating on the following memory mapped registers: // // Bus2IP_WrCE/Bus2IP_RdCE Memory Mapped Register // "1000" C_BASEADDR + 0x0 // "0100" C_BASEADDR + 0x4 // "0010" C_BASEADDR + 0x8 // "0001" C_BASEADDR + 0xC // // ------------------------------------------------------ assign slv_reg_write_sel = Bus2IP_WrCE[15:0], slv_reg_read_sel = Bus2IP_RdCE[15:0], 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] || Bus2IP_WrCE[8] || Bus2IP_WrCE[9] || Bus2IP_WrCE[10] || Bus2IP_WrCE[11] || Bus2IP_WrCE[12] || Bus2IP_WrCE[13] || Bus2IP_WrCE[14] || Bus2IP_WrCE[15], 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] || Bus2IP_RdCE[8] || Bus2IP_RdCE[9] || Bus2IP_RdCE[10] || Bus2IP_RdCE[11] || Bus2IP_RdCE[12] || Bus2IP_RdCE[13] || Bus2IP_RdCE[14] || Bus2IP_RdCE[15]; // implement slave model register(s) always @( posedge Bus2IP_Clk ) begin if ( Bus2IP_Resetn == 1'b0 ) begin slv_reg00 <= 0; slv_reg01 <= 0; slv_reg02 <= 0; slv_reg03 <= 0; slv_reg04 <= 0; slv_reg05 <= 0; slv_reg06 <= 0; slv_reg07 <= 0; slv_reg08 <= 0; slv_reg09 <= 0; slv_reg10 <= 0; slv_reg11 <= 0; slv_reg12 <= 0; slv_reg13 <= 0; slv_reg14 <= 0; slv_reg15 <= 0; end else case ( slv_reg_write_sel ) 16'b1000000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg00[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0100000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg01[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0010000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg02[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0001000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg03[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; // Mutex register // - [31] is a "lock" bit and is always writeable // - [30:0] are writeable only if [31] is zero // // NOTE: Both Bus2IP_BE and Bus2IP_Data are accessed with magic numbers vs the parameterized // values. If the data width of the slave interface is changed, then this must be updated. // 16'b0000100000000000 : if ( slv_reg04[31] == 0 ) // Check lock bit begin // Update all bytes that are enabled (includes lock bit) for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg04[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; end else begin // Update only lock bit if ( Bus2IP_BE[3] == 1 ) slv_reg04[31] <= Bus2IP_Data[31]; end 16'b0000010000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg05[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000001000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg06[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000100000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg07[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000010000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg08[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000001000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg09[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000100000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg10[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000010000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg11[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000001000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg12[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000000100 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg13[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000000010 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg14[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000000001 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg15[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; default : begin slv_reg00 <= slv_reg00; slv_reg01 <= slv_reg01; slv_reg02 <= slv_reg02; slv_reg03 <= slv_reg03; slv_reg04 <= slv_reg04; slv_reg05 <= slv_reg05; slv_reg06 <= slv_reg06; slv_reg07 <= slv_reg07; slv_reg08 <= slv_reg08; slv_reg09 <= slv_reg09; slv_reg10 <= slv_reg10; slv_reg11 <= slv_reg11; slv_reg12 <= slv_reg12; slv_reg13 <= slv_reg13; slv_reg14 <= slv_reg14; slv_reg15 <= slv_reg15; end endcase end // SLAVE_REG_WRITE_PROC // implement slave model register read mux always @* begin case ( slv_reg_read_sel ) 16'b1000000000000000 : slv_ip2bus_data <= slv_reg00_rd; 16'b0100000000000000 : slv_ip2bus_data <= slv_reg01; 16'b0010000000000000 : slv_ip2bus_data <= slv_reg02; 16'b0001000000000000 : slv_ip2bus_data <= slv_reg03_rd; 16'b0000100000000000 : slv_ip2bus_data <= slv_reg04; 16'b0000010000000000 : slv_ip2bus_data <= slv_reg05; 16'b0000001000000000 : slv_ip2bus_data <= slv_reg06; 16'b0000000100000000 : slv_ip2bus_data <= slv_reg07; 16'b0000000010000000 : slv_ip2bus_data <= slv_reg08; 16'b0000000001000000 : slv_ip2bus_data <= slv_reg09; 16'b0000000000100000 : slv_ip2bus_data <= slv_reg10; 16'b0000000000010000 : slv_ip2bus_data <= slv_reg11; 16'b0000000000001000 : slv_ip2bus_data <= slv_reg12; 16'b0000000000000100 : slv_ip2bus_data <= slv_reg13; 16'b0000000000000010 : slv_ip2bus_data <= slv_reg14; 16'b0000000000000001 : slv_ip2bus_data <= slv_reg15; default : slv_ip2bus_data <= 0; endcase end // SLAVE_REG_READ_PROC // ------------------------------------------------------------ // Example code to drive IP to Bus signals // ------------------------------------------------------------ assign IP2Bus_Data = (slv_read_ack == 1'b1) ? slv_ip2bus_data : 0 ; assign IP2Bus_WrAck = slv_write_ack; assign IP2Bus_RdAck = slv_read_ack; assign IP2Bus_Error = 0; /* Address map: HDL is coded [MSB:LSB] = [31:0] regX[31] maps to 0x80000000 in C driver regX[0] maps to 0x00000001 in C driver 00: Config/Status[31: 0]: RW [ 7: 0]: clk divider (see comments below for interpretation) RW 0x000000FF [8]: core enable (1=enabled, 0=disabled) RW 0x00000100 [15: 9]: Reserved (always zero) RO 0x0000FE00 [16]: RxACK: received ACK from slave (1=received ACK) RO 0x00010000 [17]: Busy: IIC bus busy (1 between Start and Stop events) RO 0x00020000 [18]: AL: Arbitration lost (1 when Stop detected but not requested) RO 0x00040000 [19]: TIP: Transfer in progress (1 during transfer) RO 0x00080000 [31:20]: Reserved RW 0xFFF00000 01: Command[31: 0]: RW, self-clearing, uses local reg, not normal slv_reg1 [0]: Start: generate IIC start 0x01 [1]: Stop: generate IIC stop 0x02 [2]: Read: execute IIC read 0x04 [3]: Write: execute IIC write 0x08 [4]: ACK: send ACK for current transaction 0x10 [31: 5]: Reserved 02: Transmit[31: 0]: {24'b0, txByte[7:0]} RW [ 7: 0]: Tx Byte ([31]=RNW during control word writes) [31: 8]: Reserved 03: Receive[31: 0]: {24'b0, rxByte[7:0]} RO [ 7: 0]: Rx Byte [31: 8]: Reserved 04: Mutex[31: 0]: RW (with lock bit) [30: 0]: User bits [31] : Lock 05: Serial Number [31:0]: RW [31: 0]: Serial Number 06: Ethernet A MAC address 0[31: 0]: RW [31: 0]: Ethernet A MAC address [31: 0] 07: Ethernet A MAC address 1[31: 0]: RW [15: 0]: Ethernet A MAC address [47:32] [31:16]: Reserved 08: Ethernet B MAC address 0[31: 0]: RW [31: 0]: Ethernet B MAC address [31: 0] 09: Ethernet B MAC address 1[31: 0]: RW [15: 0]: Ethernet B MAC address [47:32] [31:16]: Reserved 10: FPGA DNA 0[31: 0]: RW [31: 0]: FPGA DNA [31: 0] 11: FPGA DNA 1[31: 0]: RW [31: 0]: FPGA DNA [63:32] 12: Reserved 13: Reserved 14: Reserved 15: Reserved */ reg [4:0] cmd_reg; wire core_en; wire [15:0] clk_div; wire cmd_start, cmd_stop, cmd_read, cmd_write, cmd_ack; wire [7:0] iic_tx_byte; wire [7:0] iic_rx_byte; wire iic_rx_ack; wire iic_bus_busy; wire iic_al; wire iic_done; wire iic_tip; wire slv_reg01_WE; assign slv_reg01_WE = Bus2IP_WrCE[14]; // WrCE/RdCE[15:0] map to slv_reg[0:15] // Custom command register logic, implements self-clearing bits always @( posedge Bus2IP_Clk ) begin if ( Bus2IP_Resetn == 1'b0 ) cmd_reg <= 5'b0; else if(slv_reg01_WE == 1'b1) cmd_reg[4:0] <= Bus2IP_Data[4:0]; else if(iic_done | iic_al) begin // Clear start, stop, read, write bits on transfer completion or arbitration loss cmd_reg[3:0] <= 4'b0; cmd_reg[4] <= cmd_reg[4]; end else cmd_reg[4:0] <= cmd_reg[4:0]; end assign cmd_start = cmd_reg[0]; // 0x01 from driver assign cmd_stop = cmd_reg[1]; // 0x02 assign cmd_read = cmd_reg[2]; // 0x04 assign cmd_write = cmd_reg[3]; // 0x08 assign cmd_ack = cmd_reg[4]; // 0x10 assign iic_tip = (cmd_read | cmd_write); // Register bits self-clear on transfer completion // Construct 32-bit vectors for read access to mixed RW/RO registers wire [31:0] slv_reg00_rd; wire [31:0] slv_reg03_rd; assign slv_reg00_rd = {slv_reg00[31:20], iic_tip, iic_al, iic_bus_busy, iic_rx_ack, 7'b0, slv_reg00[8], slv_reg00[7:0]}; assign slv_reg03_rd = {24'b0, iic_rx_byte[7:0]}; // IIC master divides down master clock to generate SCL // SCL rate is (sys_clk / (5*clk_div[0:15])) // For 200MHz sys_clk and 100kHz SCL, clk_div = 400 = 0x190 // Interpret user-provided clock divider as bits[6:13] of clk_div assign clk_div[15:0] = {6'b0, slv_reg00[7:0], 2'b0}; assign core_en = slv_reg00[8]; assign iic_tx_byte = slv_reg02[7:0]; wire sda_pad_i, sda_pad_o, sda_pad_oe; wire scl_pad_i, scl_pad_o, scl_pad_oe; i2c_master_byte_ctrl byte_controller ( .clk ( Bus2IP_Clk ), // master clock .rst ( ~Bus2IP_Resetn ), // synchronous reset, active high .nReset ( 1'b1 ), // asynchronous reset, active low .ena ( core_en ), // core enable, active high .clk_cnt ( clk_div ), // master-to-iic clock divider .start ( cmd_start ), // send iic start .stop ( cmd_stop ), // send iic stop .read ( cmd_read ), // perform iic read .write ( cmd_write ), // perform iic write .ack_in ( cmd_ack ), // send iic ack .din ( iic_tx_byte ), // byte to send .cmd_ack ( iic_done ), // xfer is done .ack_out ( iic_rx_ack ), // ack from slave .dout ( iic_rx_byte ), // byte read from slave .i2c_busy ( iic_bus_busy ), .i2c_al ( iic_al ), // arbitration lost output .scl_i ( iic_scl_I ), // iic scl input (pad -> logic) .scl_o ( iic_scl_O ), // iic scl output (logic -> pad) .scl_oen ( iic_scl_T ), // iic scl output enable (0=scl is logic-driven output) .sda_i ( iic_sda_I ), // iic sda input (pad -> logic) .sda_o ( iic_sda_O ), // iic sda output (logic -> pad) .sda_oen ( iic_sda_T ) // iic sda output enable (0=sda is logic-driven output) ); endmodule