[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: gEDA-user: OT: (Vhdl help)



On Thu, Jun 26, 2008 at 02:56:22PM -0700, Ben Jackson wrote:
> On Thu, Jun 26, 2008 at 07:47:57PM +0100, Peter Clifton wrote:
> In the case of I2C where you only want inputs and pulldowns, 'O' is always
> 0 (zero) and T should be true when you want to pull down.  My own i2c
> module has inputs sda, scl and outputs sda_pull and scl_pull.  At the top
> level they're connected like:
> 
> 	assign SDA_PIN = sda_pull ? 0 : 1'bZ;
> 	assign sda = SDA_PIN;

I have lots of practice writing and using serial communication
in Xilinx, including what I believe is I2C for a TCN75.  Even
though it's Verilog, I'll attach a working (production) module
that gateways SPI and I2C devices to a non-real-time computer.

And yes, buried in there you will see the line
assign SDA75 = tcn_drive ? 1'bz : 1'b0 ;

  - Larry
// sportx.v
// Serial device support for MAX1202, MAX5742, TCN75, and ADF4001
// $Id$
// Larry Doolittle, LBNL

// llc-suite Copyright (c) 2004, The Regents of the University of
// California, through Lawrence Berkeley National Laboratory (subject
// to receipt of any required approvals from the U.S. Dept. of Energy).
// All rights reserved.

// Your use of this software is pursuant to a "BSD-style" open
// source license agreement, the text of which is in license.txt
// (md5sum a1e0e81c78f6eba050b0e96996f49fd5) that should accompany
// this file.  If the license agreement is not there, or if you
// have questions about the license, please contact Berkeley Lab's
// Technology Transfer Department at TTD@xxxxxxx referring to
// "llc-suite (LBNL Ref CR-1988)"

// November 19, 2002: TCN75 support is obviously flawed and
//   incomplete; all other device waveforms need checking
// November 25, 2002: all waveforms look proper in simulation;
//   Xilinx ISE 4.2 reports 32 FF, 70 4-LUT, 41 Slices

`timescale 1ns / 1ns

module sportx(
	input  host_clk, // interconnect
	input  host_we,  // interconnect
	input  [15:0] host_data, // interconnect
	output reg [15:0] data,     // register SPORTX_DATA
	output [15:0] status,       // register SPORTX_CNTL
	input         select_data,  // select   SPORTX_DATA
	input         select_cntl,  // select   SPORTX_CNTL
	output pll_muxout_,      // interconnect
	output reg SCLK,      // pin a
	output reg SDIN,      // pin b
	output reg CS1202,    // pin c
	output reg CS5742,    // pin d
	inout  SDA75,     // pin e
	input  DOUT1202,  // pin f
	output reg PLL_CLK,   // pin g
	output reg PLL_DATA,  // pin h
	output reg PLL_LE,    // pin i
	output reg PLL_CE,    // pin j
	input      PLL_MUXOUT // pin k
);

// reads are passive
// host_we is guaranteed to be valid for exactly one (posedge host_clk)

// ADF4001 pins are kept separate for noise reasons.
// Leave them quiet when using other devices.

// ====================end of Verilog interface definition

// Software register map:
//     16 bit data shift register
//     control:
//        0x01 running   shared for all devices
//             devsel    two bits to choose active device
//                          00 - MAX1202
//                          01 - TCN75
//                          10 - ADF4001
//                          11 - MAX5742
//        0x08 MUXOUT    from ADF4001     (read only)
//        0x10 CE        to ADF4001       (1 to turn on chip)
//        0x20 LE        to ADF4001       (0 during shifts)
//        0x40 tcn_ckhi  force TCN75 clock high (use for start/stop)
//        0x80 CS        to MAX5742       (0 during shifts)
//
// All serial devices share a common data shift register and a common
// timing state machine.  The software may only interact with one at a time.
//
// Software driver notes (also see the associated sportx_tb for example use):
//
//      all: writing a '1' to the run bit starts a serial shift operation
//           to the specified device.  Software should poll the status
//           register until that bit drops back to '0' at completion.
//
//  max1202: put the 8 control bits into the msb of data, and trigger
//           a transaction.  The 12 bits of the result land in data[14:3].
//           CS pin handling is automatic.
//
//    tcn75: Since the TCN75 SDA pin is open collector, there is no difference
//           coded here between reads and writes.  The pin status is always
//           recorded in the shift register (data).  Make sure to write a 1
//           during any bit time that you want to receive from the TCN75.
//           Transactions use 10 data bits: 8 data, 1 ack, and one trailer.
//           Create the start/stop protocol in software, using the tcn_ckhi
//           bit of the status register.  Writes to data[9] show up immediately
//           on the SDA pin; in general, data[9] of any given write should
//           match data[0] of the previous write.
//
//  adf4001: data is written 8 bits at a time.  Lower 'LE', send
//           24 bits split into three transactions, finally raise 'LE'.
//           You can turn off the chip by setting 'CE' low.  The MUXOUT
//           pin is available at all times in the status register, useful
//           if you configure that output as LD.
//
//  max5742: All 16 bits of the data are written at once.  Set 'CS' to 0
//           before transactions, and 1 afterward.

// "output reg [15:0] data" above is a shift register shared for all devices
reg running, tcn_ckhi;  // control bits, also PLL_CE, PLL_LE, CS5742
reg [1:0] devsel;
reg [4:0] divider;      // slows down incoming 25 MHz clock
reg [5:0] bitcnt;       // runs at double the bit shift rate
reg tcn_inp, tcn_clk, muxout_sample;

`ifdef SIMULATE
initial divider=0;
`endif

// This status readback is overkill, the software really only needs
// to know {muxout_sample, running}
assign status = {CS5742, tcn_ckhi, PLL_LE, PLL_CE,
	muxout_sample, devsel, running};
assign pll_muxout_ = muxout_sample;

reg tick, ldin, endc, dout, sck;
always @(devsel or bitcnt or DOUT1202 or SDA75 or muxout_sample or
         divider or data or tcn_inp or tcn_clk or tcn_ckhi or running)
	case (devsel)
 2'b00: begin // MAX1202
	// XXX fails Tcss > 100 ns
	tick = (divider[2:0] == 3'b0);  // 320 ns ticks -> 640 ns clock period
	ldin = DOUT1202;
	endc = (bitcnt == 6'd49);  // 24 clock rising edges
	dout = data[15];
	sck  = bitcnt[0] & (bitcnt[5:1] != 6'd24) & running;
	end
 2'b01: begin // TCN75
	tick = (divider == 2'b0);  // 1280 ns ticks -> 2560 ns clock period
	ldin = tcn_inp;
	endc = (bitcnt == 6'd20);  // 9 clock pulses
	dout = 1'b0;
	sck  = tcn_clk | tcn_ckhi;
	end
 2'b10: begin // ADF4001
	tick = (divider[0] == 1'b0);  // 80 ns ticks -> 160 ns clock period
	ldin = muxout_sample;  // only useful if MUXOUT=SD_out
	endc = (bitcnt == 6'd15);  // 8 clock rising edges
	dout = 1'b0;
	sck  = 1'b0;
	end
 2'b11: begin // MAX5742
	tick = (divider[0] == 1'b0);  // 80 ns ticks -> 160 ns clock period
	ldin = 1'b0;  // no readback possible; loopback analog output to verify
	endc = (bitcnt == 6'd31);  // 16 clock falling edges
	dout = data[15];
	sck  = ~bitcnt[0];
	end
endcase

wire tcn_drive = data[10] | (devsel != 2'b01);
assign SDA75 = tcn_drive ? 1'bz : 1'b0 ;

wire shift_enable = tick & running & bitcnt[0];
wire host_write_data = host_we & select_data;
wire host_write_cntl = host_we & select_cntl;

always @(posedge host_clk) begin
	divider <= divider + 1'b1;
	if (host_write_cntl | endc)
		running <= host_write_cntl & host_data[0];
	if (host_write_cntl) begin
		devsel    <= host_data[2:1];
		// host_data[3] ignored, since muxout_sample is read-only
		PLL_CE    <= host_data[4];
		PLL_LE    <= host_data[5];
		tcn_ckhi  <= host_data[6];
		CS5742    <= host_data[7];
	end
	if (shift_enable | host_write_data)
		data <= host_write_data ? host_data : {data[14:0],ldin};
	if (tick) bitcnt <= running ? (bitcnt + 1'b1) : 0 ;
	CS1202   <= ~running  | (devsel != 2'b00);
	SCLK     <= sck;
	SDIN     <= dout;
	PLL_CLK  <= bitcnt[0] & (devsel == 2'b10);
	PLL_DATA <= data[7]   & (devsel == 2'b10);
	muxout_sample <= PLL_MUXOUT;
	if (divider[4]) tcn_clk <= ~bitcnt[0] & (bitcnt[4:1] != 0) & running;
	if (tick & running & ~bitcnt[0]) tcn_inp <= SDA75;
end

endmodule

_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user