// sport.v
// Serial port driver for MEBT external ADCs and DACs
// $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@lbl.gov referring to
// "llc-suite (LBNL Ref CR-1988)"
// Initial coding: November 5, 2001
// Conversion to intercon port structure: March 2004
// 2 x DAC: MAX528
// 2 x ADC: MAX1202
// common SCLK, DIN, DOUT
// individual chip select lines
// Pin labels match those of the serial chips to which this module is
// attached, thus "DOUT" is really the input to this module, and
// "DIN" is really the output of this module.
// All logic is synchronous with the 25 MHz host computer clock.
// Logic not included here should give us a single clean "write" pulse,
// along with address and data. Output data is always valid, to
// be multiplexed, latched, and driven onto the host bus to support
// read operations.
// Serial port is driven at host clock / 16, or 1.56 MHz (640 ns period).
// The MAX1202 is rated at 2.0 MHz, the MAX528 is rated at 6 MHz.
// A MAX1202 transaction takes 25 serial port clock cycles, or 16.00 uS.
// A MAX528 transaction takes 17 serial port clock cycles, or 10.88 uS.
// The host can tell that a transaction is in progress by reading from
// this device, the low bit is "1" while the port is busy.
// addr[1:0] select device
// 00 cs0 MAX528
// 01 cs1 MAX528
// 10 cs2 MAX1202
// 11 cs3 MAX1202
// MAX528 write data format:
// a7, a6, a5, a4, a3, a2, a1, a0, d7 (msb), d6, d5, d4, d3,d2, d1, d0 (lsb)
// MAX528 read data format:
// x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, busy
// For the real MAX528 documentation, see http://www.maxim-ic.com/
// or http://dbserv.maxim-ic.com/quick_view2.cfm?qv_pk=1322
// MAX1202 write data format:
// 1, sel2, sel1, sel0, uni, sgl, pd1, pd0, 0, 0, 0, 0, 0, 0, 0, 0
// MAX1202 read data format:
// 0, b11 (msb), b10, b9, b8, b7, b6, b5, b4, b3, b2, b1, b0 (lsb), 0, 0, busy
// For the real MAX1202 documentation, see http://www.maxim-ic.com/
// or http://dbserv.maxim-ic.com/quick_view2.cfm?qv_pk=1668
`timescale 1ns / 1ns
module sport(
input rst, // interconnect
input host_clk, // interconnect
input [13:0] host_addr, // interconnect
input host_we, // interconnect
input [15:0] host_data, // interconnect
output [15:0] odata, // register SPORT
input hselect, // select SPORT
output SP_SCLK, // pin a
output SP_DIN, // pin b
input SP_DOUT, // pin c
output reg SP_CS0, // pin d
output reg SP_CS1, // pin e
output reg SP_CS2, // pin f
output reg SP_CS3 // pin g
);
reg [8:0] cnt;
reg running;
reg [15:0] data;
reg type;
reg ldin;
wire write = host_we & hselect;
assign SP_SCLK = cnt[3];
wire cke = (cnt[3:0]==15);
wire slow = cke & (type?(cnt[8:4]==23):(cnt[8:4]==15));
wire stop = cke & (type?(cnt[8:4]==24):(cnt[8:4]==15));
assign SP_DIN = data[15];
assign odata = {data[15:1],running};
always @ (posedge host_clk or posedge rst) if (rst) begin
running <= 0;
SP_CS0 <= 1;
SP_CS1 <= 1;
SP_CS2 <= 1;
SP_CS3 <= 1;
type <= 0;
ldin <= 0;
data <= 0;
cnt <= 0;
end else begin
if (write | stop) running <= write;
if (write | slow) SP_CS0 <= ~(write & ~host_addr[1] & ~host_addr[0]);
if (write | slow) SP_CS1 <= ~(write & ~host_addr[1] & host_addr[0]);
if (write | slow) SP_CS2 <= ~(write & host_addr[1] & ~host_addr[0]);
if (write | slow) SP_CS3 <= ~(write & host_addr[1] & host_addr[0]);
if (write) type <= host_addr[1];
if (cnt[3:0]==7) ldin <= SP_DOUT;
if (running ? cke : write) data <= running ? {data[14:0],ldin} : host_data;
if (running) cnt <= stop ? 0 : cnt+1;
end
endmodule