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
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
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
...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
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
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
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...