Page 8 of 19

Posted: Wed Feb 08, 2012 6:44 pm
by Dr Jefyll
Nice work, Sam -- your project looks great! You must be feeling pretty excited right about now; I know I would be :D
ElEctric_EyE wrote:
I am making many notes for V1.2...
I have a small suggestion regarding the header connectors. I notice there are no holes drilled for the unused pins. That's understandable, since you are obliged to work within the limited number of holes allowed by the PCB supplier. I believe your approach is to snip off the unused pins before each header is installed on the board.

One way to circumvent the limited hole budget is to drill the holes manually, which is a slight nuisance but really no big deal. (As a drilling template try using a scrap of pre-drilled proto-board material.) The benefit is not having to snip off the unused header pins -- so you avoid that nuisance. More to the point, in future those pins may be invaluable for mods or added circuitry!

In order to leave this option open, the space for the hole needs to be clear of other artwork. That's my suggestion for V1.2 -- route your traces as though the holes actually exist. Put an unconnected pad there perhaps. It cost nothing, and still allows people to snip the pins if they prefer.

-- Jeff
ps: more on drilling here

Posted: Wed Feb 08, 2012 9:53 pm
by ElEctric_EyE
Thanks Dr. Jeff,
I'm not so keen on drilling through the boards though. I am limited to 350 holes in that 3.8"x2.5" circuit board. It is good discipline to limit holes/via's in the first place.
I may switch manufacturers, but at this point not yet. ExpressPCB has served me well.

Also, these boards are 4 layer and have 2 power layers sandwiched in the middle.

Posted: Thu Feb 09, 2012 12:00 am
by Dr Jefyll
My mistake, overlooking the fact the board is 4 layer. I withdraw the suggestion.
-- Jeff

Posted: Thu Feb 09, 2012 12:13 am
by ElEctric_EyE
Nonetheless Dr. Jeff, Thank you for your input! It is always appreciated.

Posted: Tue Feb 14, 2012 5:51 pm
by ElEctric_EyE
Ok, I'm banging my head against the wall with this I2C core, so I had to post for help. I'm not trying to even look at the SCL/SDA lines right now, just trying to read from some of the registers that have R/W attributes. When I read all of the registers after reset, I am seeing $00. It seems to ignore all writes, except to register 1. The, whatever value I write to register 1, I am reading from all registers 0 thru 7. Sounds like memory decoding issue, but I am sure I have it correct as I am using the same design to decode PS2 and TFT chip selects... Can anyone help? This is the top level code:

Code: Select all

/////////////////////////////////////////////////////////////////////
////                                                             ////
////  WISHBONE revB.2 compliant I2C Master controller Top-level  ////
////                                                             ////
////                                                             ////
////  Author: Richard Herveille                                  ////
////          richard@asics.ws                                   ////
////          www.asics.ws                                       ////
////                                                             ////
////  Downloaded from: http://www.opencores.org/projects/i2c/    ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2001 Richard Herveille                        ////
////                    richard@asics.ws                         ////
////                                                             ////
//// This source file may be used and distributed without        ////
//// restriction provided that this copyright statement is not   ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
////                                                             ////
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
////                                                             ////
/////////////////////////////////////////////////////////////////////

//  CVS Log
//
//  $Id: i2c_master_top.v,v 1.12 2009-01-19 20:29:26 rherveille Exp $
//
//  $Date: 2009-01-19 20:29:26 $
//  $Revision: 1.12 $
//  $Author: rherveille $
//  $Locker:  $
//  $State: Exp $
//
// Change History:
//               Revision 1.11  2005/02/27 09:26:24  rherveille
//               Fixed register overwrite issue.
//               Removed full_case pragma, replaced it by a default statement.
//
//               Revision 1.10  2003/09/01 10:34:38  rherveille
//               Fix a blocking vs. non-blocking error in the wb_dat output mux.
//
//               Revision 1.9  2003/01/09 16:44:45  rherveille
//               Fixed a bug in the Command Register declaration.
//
//               Revision 1.8  2002/12/26 16:05:12  rherveille
//               Small code simplifications
//
//               Revision 1.7  2002/12/26 15:02:32  rherveille
//               Core is now a Multimaster I2C controller
//
//               Revision 1.6  2002/11/30 22:24:40  rherveille
//               Cleaned up code
//
//               Revision 1.5  2001/11/10 10:52:55  rherveille
//               Changed PRER reset value from 0x0000 to 0xffff, conform specs.
//

// synopsys translate_off
`include "timescale.v"
// synopsys translate_on

`include "i2c_master_defines.v"

module i2c_master_top(
	wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o,
	wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o,
	scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o );

	// parameters
	parameter ARST_LVL = 1'b0; // asynchronous reset level

	//
	// inputs & outputs
	//

	// wishbone signals
	input        wb_clk_i;     // master clock input
	input        wb_rst_i;     // synchronous active high reset
	input        arst_i;       // asynchronous reset
	input  [2:0] wb_adr_i;     // lower address bits
	input  [7:0] wb_dat_i;     // databus input
	output [7:0] wb_dat_o;     // databus output
	input        wb_we_i;      // write enable input
	input        wb_stb_i;     // stobe/core select signal
	input        wb_cyc_i;     // valid bus cycle input
	output       wb_ack_o;     // bus cycle acknowledge output
	output       wb_inta_o;    // interrupt request signal output

	reg [7:0] wb_dat_o;
	reg wb_ack_o;
	reg wb_inta_o;

	// I2C signals
	// i2c clock line
	input  scl_pad_i;       // SCL-line input
	output scl_pad_o;       // SCL-line output (always 1'b0)
	output scl_padoen_o;    // SCL-line output enable (active low)

	// i2c data line
	input  sda_pad_i;       // SDA-line input
	output sda_pad_o;       // SDA-line output (always 1'b0)
	output sda_padoen_o;    // SDA-line output enable (active low)


	//
	// variable declarations
	//

	// registers
	reg  [15:0] prer; // clock prescale register
	reg  [ 7:0] ctr;  // control register
	reg  [ 7:0] txr;  // transmit register
	wire [ 7:0] rxr;  // receive register
	reg  [ 7:0] cr;   // command register
	wire [ 7:0] sr;   // status register

	// done signal: command completed, clear command register
	wire done;

	// core enable signal
	wire core_en;
	wire ien;

	// status register signals
	wire irxack;
	reg  rxack;       // received aknowledge from slave
	reg  tip;         // transfer in progress
	reg  irq_flag;    // interrupt pending flag
	wire i2c_busy;    // bus busy (start signal detected)
	wire i2c_al;      // i2c bus arbitration lost
	reg  al;          // status register arbitration lost bit

	//
	// module body
	//

	// generate internal reset
	wire rst_i = arst_i ^ ARST_LVL;

	// generate wishbone signals
	wire wb_wacc = wb_we_i & wb_ack_o;

	// generate acknowledge output signal
	always @(posedge wb_clk_i)
	  wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored

	// assign DAT_O
	always @(posedge wb_clk_i)
	begin
	  case (wb_adr_i) // synopsys parallel_case
	    3'b000: wb_dat_o <= #1 prer[ 7:0];
	    3'b001: wb_dat_o <= #1 prer[15:8];
	    3'b010: wb_dat_o <= #1 ctr;
	    3'b011: wb_dat_o <= #1 rxr; // write is transmit register (txr)
	    3'b100: wb_dat_o <= #1 sr;  // write is command register (cr)
	    3'b101: wb_dat_o <= #1 txr;
	    3'b110: wb_dat_o <= #1 cr;
	    3'b111: wb_dat_o <= #1 0;   // reserved
	  endcase
	end

	// generate registers
	always @(posedge wb_clk_i or negedge rst_i)
	  if (!rst_i)
	    begin
	        prer <= #1 16'hffff;
	        ctr  <= #1  8'h0;
	        txr  <= #1  8'h0;
	    end
	  else if (wb_rst_i)
	    begin
	        prer <= #1 16'hffff;
	        ctr  <= #1  8'h0;
	        txr  <= #1  8'h0;
	    end
	  else
	    if (wb_wacc)
	      case (wb_adr_i) // synopsys parallel_case
	         3'b000 : prer [ 7:0] <= #1 wb_dat_i;
	         3'b001 : prer [15:8] <= #1 wb_dat_i;
	         3'b010 : ctr         <= #1 wb_dat_i;
	         3'b011 : txr         <= #1 wb_dat_i;
	         default: ;
	      endcase

	// generate command register (special case)
	always @(posedge wb_clk_i or negedge rst_i)
	  if (!rst_i)
	    cr <= #1 8'h0;
	  else if (wb_rst_i)
	    cr <= #1 8'h0;
	  else if (wb_wacc)
	    begin
	        if (core_en & (wb_adr_i == 3'b100) )
	          cr <= #1 wb_dat_i;
	    end
	  else
	    begin
	        if (done | i2c_al)
	          cr[7:4] <= #1 4'h0;           // clear command bits when done
	                                        // or when aribitration lost
	        cr[2:1] <= #1 2'b0;             // reserved bits
	        cr[0]   <= #1 1'b0;             // clear IRQ_ACK bit
	    end


	// decode command register
	wire sta  = cr[7];
	wire sto  = cr[6];
	wire rd   = cr[5];
	wire wr   = cr[4];
	wire ack  = cr[3];
	wire iack = cr[0];

	// decode control register
	assign core_en = ctr[7];
	assign ien = ctr[6];

	// hookup byte controller block
	i2c_master_byte_ctrl byte_controller (
		.clk      ( wb_clk_i     ),
		.rst      ( wb_rst_i     ),
		.nReset   ( rst_i        ),
		.ena      ( core_en      ),
		.clk_cnt  ( prer         ),
		.start    ( sta          ),
		.stop     ( sto          ),
		.read     ( rd           ),
		.write    ( wr           ),
		.ack_in   ( ack          ),
		.din      ( txr          ),
		.cmd_ack  ( done         ),
		.ack_out  ( irxack       ),
		.dout     ( rxr          ),
		.i2c_busy ( i2c_busy     ),
		.i2c_al   ( i2c_al       ),
		.scl_i    ( scl_pad_i    ),
		.scl_o    ( scl_pad_o    ),
		.scl_oen  ( scl_padoen_o ),
		.sda_i    ( sda_pad_i    ),
		.sda_o    ( sda_pad_o    ),
		.sda_oen  ( sda_padoen_o )
	);

	// status register block + interrupt request signal
	always @(posedge wb_clk_i or negedge rst_i)
	  if (!rst_i)
	    begin
	        al       <= #1 1'b0;
	        rxack    <= #1 1'b0;
	        tip      <= #1 1'b0;
	        irq_flag <= #1 1'b0;
	    end
	  else if (wb_rst_i)
	    begin
	        al       <= #1 1'b0;
	        rxack    <= #1 1'b0;
	        tip      <= #1 1'b0;
	        irq_flag <= #1 1'b0;
	    end
	  else
	    begin
	        al       <= #1 i2c_al | (al & ~sta);
	        rxack    <= #1 irxack;
	        tip      <= #1 (rd | wr);
	        irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated
	    end

	// generate interrupt request signals
	always @(posedge wb_clk_i or negedge rst_i)
	  if (!rst_i)
	    wb_inta_o <= #1 1'b0;
	  else if (wb_rst_i)
	    wb_inta_o <= #1 1'b0;
	  else
	    wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set)

	// assign status register bits
	assign sr[7]   = rxack;
	assign sr[6]   = i2c_busy;
	assign sr[5]   = al;
	assign sr[4:2] = 3'h0; // reserved
	assign sr[1]   = tip;
	assign sr[0]   = irq_flag;

endmodule

Posted: Wed Feb 15, 2012 8:28 pm
by ElEctric_EyE
I have been trying to implement the Verilog version of Richard's I2C Core. Today I looked a little deeper into the repository at opencores.org and found out he has been updating the VHDL version... I will focus on this next.

Posted: Sun Feb 26, 2012 3:34 pm
by BigEd
Have you had a look at the internal control signals and register values in isim? That should help you see whether your memory decode is right. That is, it's worth stepping down below the machine code level to the implementation level. (Unless you've already done that! In which case, maybe the wishbone bus has something odd going on with timing?)

Cheers
Ed

Posted: Wed Feb 29, 2012 7:05 pm
by ElEctric_EyE
BigEd wrote:
Have you had a look at the internal control signals and register values in isim? That should help you see whether your memory decode is right. That is, it's worth stepping down below the machine code level to the implementation level. (Unless you've already done that! In which case, maybe the wishbone bus has something odd going on with timing?)

Cheers
Ed
Hi Ed, welcome back. I haven't tried the I2C core yet in ISim, but I think it's time I tried!

Hmmm, I forgot: I did try the core in ISim and it didn't work.

Posted: Wed Feb 29, 2012 7:40 pm
by Arlet
For some quick I2C results, you could make a simple IO peripheral, and bit-bang the SCL and SDA lines in software. If you intend to have the CPU core wait for I2C transactions to finish, there's not much advantage in doing I2C in hardware.

Posted: Wed Feb 29, 2012 7:53 pm
by Arlet
By the way, since I just received my board, I was wondering... is the +5V connected to anything on the board ? I can only see it attached to the keyboard connector.

I only have a power supply with a single output, so if I don't need the 5V right now, I would like to leave it unconnected. Is that okay ?

Posted: Wed Feb 29, 2012 9:12 pm
by ElEctric_EyE
Arlet wrote:
...I only have a power supply with a single output, so if I don't need the 5V right now, I would like to leave it unconnected. Is that okay ?
Excellent!
Yes, the 5VDC input is meant for the PS2 keyboard connector (which you are not using), 3 pins on Header 3 (for a potential future daughterboard), and a larger current passing via intended for a 5V to 10V DC-DC converter for TFT backlight LEDs.

Posted: Fri Mar 02, 2012 12:54 am
by ElEctric_EyE
Arlet wrote:
For some quick I2C results, you could make a simple IO peripheral, and bit-bang the SCL and SDA lines in software. If you intend to have the CPU core wait for I2C transactions to finish, there's not much advantage in doing I2C in hardware.
I am one step away from this. I know Garth has said he did it successfully. I tire of this I2C Core!
I don't need multimaster I2C anyway....

I just pursued the Core for so long because I hate software overhead. But now that I think about it, out of all the devices I have on the I2C bus will not need alot of attention except for the TSC2003 touchscreen controller. Experimental for the TFT I am using.

Posted: Wed Mar 07, 2012 1:58 am
by ElEctric_EyE
Arlet wrote:
By the way, since I just received my board...
Does Xilinx iMPACT see the 2 devices? (Spartan 6 and PROM). Are you having any sort of success?

Posted: Wed Mar 07, 2012 5:37 am
by Arlet
ElEctric_EyE wrote:
Does Xilinx iMPACT see the 2 devices? (Spartan 6 and PROM). Are you having any sort of success?
I haven't had time yet. Been too busy with customer projects. I'll give it a shot next weekend.

Posted: Wed Mar 07, 2012 9:23 pm
by ElEctric_EyE
Ah, no rush. Just wondering...