1//////////////////////////////////////////////////////////////////////////////
2//                                                                          //
3//  Minimalistic 1-wire (onewire) master with Avalon MM bus interface       //
4//                                                                          //
5//  Copyright (C) 2010  Iztok Jeras                                         //
6//                                                                          //
7//////////////////////////////////////////////////////////////////////////////
8//                                                                          //
9//  This RTL is free hardware: you can redistribute it and/or modify        //
10//  it under the terms of the GNU Lesser General Public License             //
11//  as published by the Free Software Foundation, either                    //
12//  version 3 of the License, or (at your option) any later version.        //
13//                                                                          //
14//  This RTL is distributed in the hope that it will be useful,             //
15//  but WITHOUT ANY WARRANTY; without even the implied warranty of          //
16//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
17//  GNU General Public License for more details.                            //
18//                                                                          //
19//  You should have received a copy of the GNU General Public License       //
20//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
21//                                                                          //
22//////////////////////////////////////////////////////////////////////////////
23
24//////////////////////////////////////////////////////////////////////////////
25//  Modifications:
26//      2016-08-24: by Jan Pospisil (j.pospisil@cern.ch)
27//          * added default values; typos
28//////////////////////////////////////////////////////////////////////////////
29
30//////////////////////////////////////////////////////////////////////////////
31//                                                                          //
32// The clock divider parameter is computed with the next formula:           //
33//                                                                          //
34// CDR_N = f_CLK * BTP_N - 1  (example: CDR_N = 1MHz * 5.0us - 1 = 5-1)     //
35// CDR_O = f_CLK * BTP_O - 1  (example: CDR_O = 1MHz * 1.0us - 1 = 1-1)     //
36//                                                                          //
37// If the dividing factor is not a round integer, than the timing of the    //
38// controller will be slightly off, and would support only a subset of      //
39// 1-wire devices with timing closer to the typical 30us slot.              //
40//                                                                          //
41// Base time periods BTP_N = "5.0" and BTP_O = "1.0" are optimized for      //
42// onewire timing. The default timing restricts the range of available      //
43// frequences to multiples of 1MHz.                                         //
44//                                                                          //
45// If even this restrictions are too strict use timing BTP_N = "6.0" and    //
46// BTP_O = "0.5", where the actual periods can be in the range:             //
47// 6.0us <= BTP_N <= 7.5us                                                  //
48// 0.5us <= BTP_O <= 0.66us                                                 //
49//                                                                          //
50// A third timing option is available for normal mode BTP_N = "7.5", this   //
51// option is optimized for logic size.                                      //
52//                                                                          //
53//////////////////////////////////////////////////////////////////////////////
54
55module sockit_owm #(
56  // enable implementation of optional functionality
57  parameter OVD_E =    1,  // overdrive functionality is implemented by default
58  parameter CDR_E =    1,  // clock divider register is implemented by default
59  // interface parameters
60  parameter BDW   =   32,  // bus data width
61  parameter OWN   =    1,  // number of 1-wire ports
62  // computed bus address port width
63`ifdef __ICARUS__
64  parameter BAW   = (BDW==32) ? 1 : 2,
65`else
66  parameter BAW   = 1,  // TODO, the above is correct, but does not work well with Altera SOPC Builder
67`endif
68  // base time period
69  parameter BTP_N = "5.0", // normal    mode (5.0us, options are "7.5", "5.0" and "6.0")
70  parameter BTP_O = "0.5", // overdrive mode (1.0us, options are "1.0",       and "0.5")
71  // normal mode timing
72  parameter T_RSTH_N = (BTP_N == "7.5") ?  64 : (BTP_N == "5.0") ?  96 :  80,  // reset high
73  parameter T_RSTL_N = (BTP_N == "7.5") ?  64 : (BTP_N == "5.0") ?  96 :  80,  // reset low
74  parameter T_RSTP_N = (BTP_N == "7.5") ?  10 : (BTP_N == "5.0") ?  15 :  10,  // reset presence pulse
75  parameter T_DAT0_N = (BTP_N == "7.5") ?   8 : (BTP_N == "5.0") ?  12 :  10,  // bit 0 low
76  parameter T_DAT1_N = (BTP_N == "7.5") ?   1 : (BTP_N == "5.0") ?   1 :   1,  // bit 1 low
77  parameter T_BITS_N = (BTP_N == "7.5") ?   2 : (BTP_N == "5.0") ?   3 :   2,  // bit sample
78  parameter T_RCVR_N = (BTP_N == "7.5") ?   1 : (BTP_N == "5.0") ?   1 :   1,  // recovery
79  parameter T_IDLE_N = (BTP_N == "7.5") ? 128 : (BTP_N == "5.0") ? 200 : 160,  // idle timer
80  // overdrive mode timing
81  parameter T_RSTH_O = (BTP_O == "1.0") ?  48 :  96,  // reset high
82  parameter T_RSTL_O = (BTP_O == "1.0") ?  48 :  96,  // reset low
83  parameter T_RSTP_O = (BTP_O == "1.0") ?  10 :  15,  // reset presence pulse
84  parameter T_DAT0_O = (BTP_O == "1.0") ?   6 :  12,  // bit 0 low
85  parameter T_DAT1_O = (BTP_O == "1.0") ?   1 :   2,  // bit 1 low
86  parameter T_BITS_O = (BTP_O == "1.0") ?   2 :   3,  // bit sample
87  parameter T_RCVR_O = (BTP_O == "1.0") ?   2 :   4,  // recovery
88  parameter T_IDLE_O = (BTP_O == "1.0") ?  96 : 192,  // idle timer
89  // clock divider ratios (defaults are for a 1MHz clock)
90  parameter CDR_N = 5-1,  // normal    mode
91  parameter CDR_O = 1-1   // overdrive mode
92)(
93  // system signals
94  input            clk,
95  input            rst,
96  // CPU bus interface
97  input            bus_ren,  // read  enable
98  input            bus_wen,  // write enable
99  input  [BAW-1:0] bus_adr,  // address
100  input  [BDW-1:0] bus_wdt,  // write data
101  output [BDW-1:0] bus_rdt,  // read  data
102  output           bus_irq,  // interrupt request
103  // 1-wire interface
104  output [OWN-1:0] owr_p,    // output power enable
105  output [OWN-1:0] owr_e,    // output pull down enable
106  input  [OWN-1:0] owr_i     // input from bidirectional wire
107);
108
109//////////////////////////////////////////////////////////////////////////////
110// local parameters
111//////////////////////////////////////////////////////////////////////////////
112
113function integer clogb2;
114input [31:0] value;
115begin
116   for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
117     value = value >> 1;
118end
119endfunction
120
121// size of combined power and select registers
122localparam PDW = (BDW==32) ? 24 : 8;
123
124// size of boudrate generator counter (divider for normal mode is largest)
125localparam CDW = CDR_E ? ((BDW==32) ? 16 : 8) : clogb2(CDR_N);
126
127// size of port select signal
128localparam SDW = clogb2(OWN);
129
130// size of cycle timing counter
131localparam TDW =       (T_RSTH_O+T_RSTL_O) >       (T_RSTH_N+T_RSTL_N)
132               ? clogb2(T_RSTH_O+T_RSTL_O) : clogb2(T_RSTH_N+T_RSTL_N);
133
134//////////////////////////////////////////////////////////////////////////////
135// local signals
136//////////////////////////////////////////////////////////////////////////////
137
138// address dependent write enable
139wire bus_ren_ctl_sts;
140wire bus_wen_ctl_sts;
141wire bus_wen_pwr_sel;
142wire bus_wen_cdr_n;
143wire bus_wen_cdr_o;
144
145// read data bus segments
146wire     [7:0] bus_rdt_ctl_sts;
147wire [PDW-1:0] bus_rdt_pwr_sel;
148
149// clock divider
150reg  [CDW-1:0] div;
151reg  [CDW-1:0] cdr_n = CDR_N[CDW-1:0];
152reg  [CDW-1:0] cdr_o = CDR_O[CDW-1:0];
153wire           pls;
154
155// cycle control and status
156reg            owr_cyc;  // cycle status
157reg  [TDW-1:0] cnt;      // cycle counter
158
159// port select
160//generate if (OWN>1) begin : sel_declaration
161reg  [SDW-1:0] owr_sel;
162//end endgenerate
163
164// modified input data for overdrive
165wire           req_ovd;
166
167// onewire signals
168reg  [OWN-1:0] owr_pwr;  // power
169reg            owr_ovd;  // overdrive
170reg            owr_rst;  // reset
171reg            owr_dat;  // data bit
172reg            owr_smp;  // sample bit
173
174reg            owr_oen;  // output enable
175wire           owr_iln;  // input line
176
177// interrupt signals
178reg            irq_ena;  // interrupt enable
179reg            irq_sts;  // interrupt status
180
181// timing signals
182wire [TDW-1:0] t_idl ;   // idle                 cycle    time
183wire [TDW-1:0] t_rst ;   // reset                cycle    time
184wire [TDW-1:0] t_bit ;   // data bit             cycle    time
185wire [TDW-1:0] t_rstp;   // reset presence pulse sampling time
186wire [TDW-1:0] t_rsth;   // reset                release  time
187wire [TDW-1:0] t_dat0;   // data bit 0           release  time
188wire [TDW-1:0] t_dat1;   // data bit 1           release  time
189wire [TDW-1:0] t_bits;   // data bit             sampling time
190wire [TDW-1:0] t_zero;   // end of               cycle    time
191
192//////////////////////////////////////////////////////////////////////////////
193// cycle timing
194//////////////////////////////////////////////////////////////////////////////
195
196// idle time
197assign t_idl  = req_ovd ? T_IDLE_O[TDW-1:0]                         : T_IDLE_N[TDW-1:0];
198// reset cycle time (reset low + reset hight)
199assign t_rst  = req_ovd ? T_RSTL_O[TDW-1:0] + T_RSTH_O[TDW-1:0]     : T_RSTL_N[TDW-1:0] + T_RSTH_N[TDW-1:0];
200// data bit cycle time (write 0 + recovery)
201assign t_bit  = req_ovd ? T_DAT0_O[TDW-1:0] + T_RCVR_O[TDW-1:0]     : T_DAT0_N[TDW-1:0] + T_RCVR_N[TDW-1:0];
202
203// reset presence pulse sampling time (reset high - reset presence)
204assign t_rstp = owr_ovd ? T_RSTH_O[TDW-1:0] - T_RSTP_O[TDW-1:0]     : T_RSTH_N[TDW-1:0] - T_RSTP_N[TDW-1:0];
205// reset      release time (reset high)
206assign t_rsth = owr_ovd ? T_RSTH_O[TDW-1:0]                         : T_RSTH_N[TDW-1:0];
207
208// data bit 0 release time (write bit 0 - write bit 0 + recovery)
209assign t_dat0 = owr_ovd ? T_DAT0_O[TDW-1:0] - T_DAT0_O[TDW-1:0] + T_RCVR_O[TDW-1:0] : T_DAT0_N[TDW-1:0] - T_DAT0_N[TDW-1:0] + T_RCVR_N[TDW-1:0];
210// data bit 1 release time (write bit 0 - write bit 1 + recovery)
211assign t_dat1 = owr_ovd ? T_DAT0_O[TDW-1:0] - T_DAT1_O[TDW-1:0] + T_RCVR_O[TDW-1:0] : T_DAT0_N[TDW-1:0] - T_DAT1_N[TDW-1:0] + T_RCVR_N[TDW-1:0];
212// data bit sampling time (write bit 0 - write bit 1 + recovery)
213assign t_bits = owr_ovd ? T_DAT0_O[TDW-1:0] - T_BITS_O[TDW-1:0] + T_RCVR_O[TDW-1:0] : T_DAT0_N[TDW-1:0] - T_BITS_N[TDW-1:0] + T_RCVR_N[TDW-1:0];
214
215// end of cycle time
216assign t_zero = 'd0;
217
218//////////////////////////////////////////////////////////////////////////////
219// bus read
220//////////////////////////////////////////////////////////////////////////////
221
222// bus segnemt - controll/status register
223assign bus_rdt_ctl_sts = {irq_ena, irq_sts, 1'b0, owr_pwr[0], owr_cyc, owr_ovd, owr_rst, owr_dat};
224
225// bus segnemt - power and select register
226generate
227  if (BDW==32) begin
228    if (OWN>1) begin
229      assign bus_rdt_pwr_sel = {{16-OWN{1'b0}}, owr_pwr, 4'h0, {4-SDW{1'b0}}, owr_sel};
230    end else begin
231      assign bus_rdt_pwr_sel = 24'h0000_00;
232    end
233  end else if (BDW==8) begin
234    if (OWN>1) begin
235      assign bus_rdt_pwr_sel = {{ 4-OWN{1'b0}}, owr_pwr,       {4-SDW{1'b0}}, owr_sel};
236    end else begin
237      assign bus_rdt_pwr_sel = 8'hxx;
238    end
239  end
240endgenerate
241
242// bus read data
243generate if (BDW==32) begin
244  assign bus_rdt = (bus_adr[0]==1'b0) ? {bus_rdt_pwr_sel, bus_rdt_ctl_sts} : (cdr_o << 16 | cdr_n);
245end else if (BDW==8) begin
246  assign bus_rdt = (bus_adr[1]==1'b0) ? ((bus_adr[0]==1'b0) ? bus_rdt_ctl_sts
247                                                            : bus_rdt_pwr_sel)
248                                      : ((bus_adr[0]==1'b0) ? cdr_n
249                                                            : cdr_o          );
250end endgenerate
251
252//////////////////////////////////////////////////////////////////////////////
253// bus write
254//////////////////////////////////////////////////////////////////////////////
255
256// combined write/read enable and address decoder
257generate if (BDW==32) begin
258  assign bus_ren_ctl_sts = bus_ren & bus_adr[0] == 1'b0;
259  assign bus_wen_ctl_sts = bus_wen & bus_adr[0] == 1'b0;
260  assign bus_wen_pwr_sel = bus_wen & bus_adr[0] == 1'b0;
261  assign bus_wen_cdr_n   = bus_wen & bus_adr[0] == 1'b1;
262  assign bus_wen_cdr_o   = bus_wen & bus_adr[0] == 1'b1;
263end else if (BDW==8) begin
264  assign bus_ren_ctl_sts = bus_ren & bus_adr[1:0] == 2'b00;
265  assign bus_wen_ctl_sts = bus_wen & bus_adr[1:0] == 2'b00;
266  assign bus_wen_pwr_sel = bus_wen & bus_adr[1:0] == 2'b01;
267  assign bus_wen_cdr_n   = bus_wen & bus_adr[1:0] == 2'b10;
268  assign bus_wen_cdr_o   = bus_wen & bus_adr[1:0] == 2'b11;
269end endgenerate
270
271//////////////////////////////////////////////////////////////////////////////
272// clock divider
273//////////////////////////////////////////////////////////////////////////////
274
275// clock divider ratio registers
276generate
277  if (CDR_E) begin
278    if (BDW==32) begin
279      always @ (posedge clk, posedge rst)
280      if (rst) begin
281        cdr_n <= CDR_N[CDW-1:0];
282        cdr_o <= CDR_O[CDW-1:0];
283      end else begin
284        if (bus_wen_cdr_n)  cdr_n <= bus_wdt[15: 0];
285        if (bus_wen_cdr_o)  cdr_o <= bus_wdt[31:16];
286      end
287    end else if (BDW==8) begin
288      always @ (posedge clk, posedge rst)
289      if (rst) begin
290        cdr_n <= CDR_N[CDW-1:0];
291        cdr_o <= CDR_O[CDW-1:0];
292      end else begin
293        if (bus_wen_cdr_n)  cdr_n <= bus_wdt;
294        if (bus_wen_cdr_o)  cdr_o <= bus_wdt;
295      end
296    end
297  end else begin
298    initial begin
299      cdr_n = CDR_N[CDW-1:0];
300      cdr_o = CDR_O[CDW-1:0];
301    end
302  end
303endgenerate
304
305// clock divider
306always @ (posedge clk, posedge rst)
307if (rst)        div <= {CDW{1'd0}};
308else begin
309  if (bus_wen)  div <= {CDW{1'd0}};
310  else          div <= pls ? {CDW{1'd0}} : div + owr_cyc;
311end
312
313// divided clock pulse
314assign pls = (div == (owr_ovd ? cdr_o : cdr_n));
315
316//////////////////////////////////////////////////////////////////////////////
317// power and select register
318//////////////////////////////////////////////////////////////////////////////
319
320// select and power register implementation
321generate if (OWN>1) begin : sel_implementation
322  // port select
323  always @ (posedge clk, posedge rst)
324  if (rst)                   owr_sel <= {SDW{1'b0}};
325  else if (bus_wen_pwr_sel)  owr_sel <= bus_wdt[(BDW==32 ?  8 : 0)+:SDW];
326
327  // power delivery
328  always @ (posedge clk, posedge rst)
329  if (rst)                   owr_pwr <= {OWN{1'b0}};
330  else if (bus_wen_pwr_sel)  owr_pwr <= bus_wdt[(BDW==32 ? 16 : 4)+:OWN];
331end else begin
332  // port select
333  initial                    owr_sel <= 'd0;
334  // power delivery
335  always @ (posedge clk, posedge rst)
336  if (rst)                   owr_pwr <= 1'b0;
337  else if (bus_wen_ctl_sts)  owr_pwr <= bus_wdt[4];
338end endgenerate
339
340//////////////////////////////////////////////////////////////////////////////
341// interrupt logic
342//////////////////////////////////////////////////////////////////////////////
343
344// bus interrupt
345assign bus_irq = irq_ena & irq_sts;
346
347// interrupt enable
348always @ (posedge clk, posedge rst)
349if (rst)                   irq_ena <= 1'b0;
350else if (bus_wen_ctl_sts)  irq_ena <= bus_wdt[7];
351
352// transmit status (active after onewire cycle ends)
353always @ (posedge clk, posedge rst)
354if (rst)                           irq_sts <= 1'b0;
355else begin
356  if (bus_wen_ctl_sts)             irq_sts <= 1'b0;
357  else if (pls & (cnt == t_zero))  irq_sts <= 1'b1;
358  else if (bus_ren_ctl_sts)        irq_sts <= 1'b0;
359end
360
361//////////////////////////////////////////////////////////////////////////////
362// onewire state machine
363//////////////////////////////////////////////////////////////////////////////
364
365assign req_ovd = OVD_E ? bus_wen_ctl_sts & bus_wdt[2] : 1'b0;
366
367// overdrive
368always @ (posedge clk, posedge rst)
369if (rst)                   owr_ovd <= 1'b0;
370else if (bus_wen_ctl_sts)  owr_ovd <= req_ovd;
371
372// reset
373always @ (posedge clk, posedge rst)
374if (rst)                   owr_rst <= 1'b0;
375else if (bus_wen_ctl_sts)  owr_rst <= bus_wdt[1];
376
377// transmit data, reset, overdrive
378always @ (posedge clk, posedge rst)
379if (rst)                           owr_dat <= 1'b0;
380else begin
381  if (bus_wen_ctl_sts)             owr_dat <= bus_wdt[0];
382  else if (pls & (cnt == t_zero))  owr_dat <= owr_smp;
383end
384
385// onewire cycle status
386always @ (posedge clk, posedge rst)
387if (rst)                           owr_cyc <= 1'b0;
388else begin
389  if (bus_wen_ctl_sts)             owr_cyc <= bus_wdt[3] & ~&bus_wdt[2:0];
390  else if (pls & (cnt == t_zero))  owr_cyc <= 1'b0;
391end
392
393// state counter (initial value depends whether the cycle is reset or data)
394always @ (posedge clk, posedge rst)
395if (rst)                 cnt <= 0;
396else begin
397  if (bus_wen_ctl_sts)   cnt <= (&bus_wdt[1:0] ? t_idl : bus_wdt[1] ? t_rst : t_bit) - 1'd1;
398  else if (pls)          cnt <= cnt - 1'd1;
399end
400
401// receive data (sampling point depends whether the cycle is reset or data)
402always @ (posedge clk)
403if (pls) begin
404  if      ( owr_rst & (cnt == t_rstp))  owr_smp <= owr_iln;  // presence detect
405  else if (~owr_rst & (cnt == t_bits))  owr_smp <= owr_iln;  // read data bit
406end
407
408// output register (switch point depends whether the cycle is reset or data)
409always @ (posedge clk, posedge rst)
410if (rst)                                owr_oen <= 1'b0;
411else begin
412  if (bus_wen_ctl_sts)                  owr_oen <= ~&bus_wdt[1:0];
413  else if (pls) begin
414    if      (owr_rst & (cnt == t_rsth)) owr_oen <= 1'b0;  // reset
415    else if (owr_dat & (cnt == t_dat1)) owr_oen <= 1'b0;  // write 1, read
416    else if (          (cnt == t_dat0)) owr_oen <= 1'b0;  // write 0
417  end
418end
419
420//////////////////////////////////////////////////////////////////////////////
421// IO
422//////////////////////////////////////////////////////////////////////////////
423
424// only one 1-wire line can be accessed at the same time
425assign owr_e   = owr_oen << owr_sel;
426// all 1-wire lines can be powered independently
427assign owr_p   = owr_pwr;
428
429// 1-wire line status read multiplexer
430assign owr_iln = owr_i [owr_sel];
431
432endmodule
433