[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