// Serial port driver for external ADCs and DACs // SNS LLRF Digital board // Target: XC2S150 // Larry Doolittle // November 5, 2001 // 2 x DAC: MAX528 // 2 x ADC: MAX1202 // common sclk, din, dout // individual chip select lines // 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 // MAX1201 write data format: // 1, sel2, sel1, sel0, uni, sgl, pd1, pd0, 0, 0, 0, 0, 0, 0, 0, 0 // MAX1201 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(clk, write, addr, idata, odata, sclk, din, dout, cs0, cs1, cs2, cs3); input clk, write, din; output [15:0] odata; output sclk, dout, cs0, cs1, cs2, cs3; wire clk, write, din; input [1:0] addr; wire [1:0] addr; input [15:0] idata; wire [15:0] idata; reg [8:0] cnt; reg running; reg [15:0] data; reg cs0, cs1, cs2, cs3; reg type; reg ldin; wire sclk; assign sclk=cnt[3]; wire cke; assign cke=(cnt[3:0]==15); wire slow; assign slow=cke&(type?(cnt[8:4]==16):(cnt[8:4]==24)); wire stop; assign stop=cke&(type?(cnt[8:4]==17):(cnt[8:4]==25)); wire dout; assign dout=data[15]; wire [15:0] odata={data[15:1],running}; always @ (posedge clk) begin if (write | stop) running <= write; if (write | slow) cs0 <= ~(write & ~addr[1] & ~addr[0]); if (write | slow) cs1 <= ~(write & ~addr[1] & addr[0]); if (write | slow) cs2 <= ~(write & addr[1] & ~addr[0]); if (write | slow) cs3 <= ~(write & addr[1] & addr[0]); if (write) type <= addr[1]; if (cnt[3:0]==7) ldin<=din; if (running ? cke : write) data <= running ? {data[14:0],ldin} : idata; if (running) cnt <= stop ? 0 : cnt+1; end initial begin running = 0; cnt = 0; cs0 = 1; cs1 = 1; cs2 = 1; cs3 = 1; end endmodule