// ds2401_driver.v
// Dallas 1-Wire[TM] serial number driver
// $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: October 29, 2002
//
// exit reset: Z0ZZZZZZZZZZRZZ
// write a zero: Z0000000000000Z >60 uS low
// write a one: Z0111111111111Z 5 uS low, >60 uS total
// read a bit: Z0ZZRZZZZZZZZZZ 5 uS low, 15 uS from first 0 to R
// count 0123456789abcd0
// one "slot" should be a little over 60 uS
//
// My simple-minded counting of registers and "difficult" logic
// gives about 26 Cells in an FPGA. Xilinx ISE 4.2i says it
// implements in 17 slices (34 cells).
//
// write register: { write_data2, write_data1, reset, run }
// read register: { count, run, read_presence, read_data }
//
// November 20, 2002: I changed this to report (count!=0 | run) instead
// of { count, run }. This makes the interface to the software cleaner,
// and actually reduces the logic footprint, since more bits in the output
// mean more multiplexers used to fan-in to the host. The change is
// backward compatible: the software can still check for completion
// using a mask of 0x7c (zero count & zero run), since we force unused
// read_bus bits to zero.
//
// Reset:
// write 0010; wait at least 480 us;
// write 1101; wait at least 480 us;
// check read_presence bit
// Write a bit:
// write b001; poll until run==0
// Read a bit:
// write 1001; poll until run==0, use read_data
// Note that the output is the same for reading a bit and writing a 1.
// This is correct. read_data should be 1 after writing a 1.
`timescale 1ns / 1ns
module ds2401_driver(
input host_clk, // interconnect
inout DS2401, // pin c3
input host_we, // interconnect
input [15:0] host_data, // interconnect
output [15:0] read_bus, // register DS2401
input select // select DS2401
);
reg [6:0] divider;
`ifdef SIMULATE
initial divider=0;
`endif
reg tick;
always @(posedge host_clk) begin
divider <= divider + 1'b1;
tick <= (divider == 0);
end
reg [3:0] count;
wire zero_count = (count == 4'd0);
wire indata_count = (count == 4'd3);
wire end_of_count = (count == 4'd13);
reg run, reset, write_data1, write_data2;
always @(posedge host_clk) begin
if (host_we & select | tick & end_of_count) begin
run <= host_we & select & host_data[0];
end
if (host_we & select) begin
reset <= host_data[1];
write_data1 <= host_data[2];
write_data2 <= host_data[3];
end
end
reg drive, read_data, read_presence;
always @(posedge host_clk) if (tick) begin
count <= run ? (count + 1'b1) : 0;
drive <= reset | run & ~end_of_count &
~(zero_count ? write_data1 : write_data2);
if (indata_count) read_data <= DS2401;
if (end_of_count) read_presence <= DS2401;
end
assign DS2401 = drive ? 1'b0 : 1'bz;
assign read_bus = { 13'b0100000000000,
~zero_count | run, read_presence, read_data };
endmodule