OpenCores
URL https://opencores.org/ocsvn/sockit_owm/sockit_owm/trunk

Subversion Repositories sockit_owm

[/] [sockit_owm/] [trunk/] [hdl/] [onewire_tb.v] - Diff between revs 2 and 3

Show entire file | Details | Blame | View Log

Rev 2 Rev 3
Line 1... Line 1...
 
//////////////////////////////////////////////////////////////////////////////                                                                                          
 
//                                                                          //
 
//  Minimalistic 1-wire (onewire) master with Avalon MM bus interface       //
 
//  testbench                                                               //
 
//                                                                          //
 
//  Copyright (C) 2010  Iztok Jeras                                         //
 
//                                                                          //
 
//////////////////////////////////////////////////////////////////////////////
 
//                                                                          //
 
//  This RTL is free hardware: you can redistribute it and/or modify        //
 
//  it under the terms of the GNU Lesser General Public License             //
 
//  as published by the Free Software Foundation, either                    //
 
//  version 3 of the License, or (at your option) any later version.        //
 
//                                                                          //
 
//  This RTL is distributed in the hope that it will be useful,             //
 
//  but WITHOUT ANY WARRANTY; without even the implied warranty of          //
 
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
 
//  GNU General Public License for more details.                            //
 
//                                                                          //
 
//  You should have received a copy of the GNU General Public License       //
 
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
 
//                                                                          //
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
`timescale 1ns / 1ps
 
 
 
module onewire_tb;
 
 
 
localparam DEBUG = 1'b0;
 
 
 
// system clock parameters
 
localparam real FRQ = 6_000_000;      // frequency 6MHz
 
localparam real TCP = (10.0**9)/FRQ;  // time clock period in ns
 
 
 
`ifdef CDR_E
 
localparam CDR_E = 1;
 
`else
 
localparam CDR_E = 0;
 
`endif
 
 
 
`ifdef PRESET_50_10
 
localparam OVD_E = 1'b1;   // overdrive functionality enable
 
localparam BTP_N = "5.0";  // normal    mode
 
localparam BTP_O = "1.0";  // overdrive mode
 
`elsif PRESET_60_05
 
localparam OVD_E = 1'b1;   // overdrive functionality enable
 
localparam BTP_N = "6.0";  // normal    mode
 
localparam BTP_O = "0.5";  // overdrive mode
 
`elsif PRESET_75
 
localparam OVD_E = 1'b0;   // overdrive functionality enable
 
localparam BTP_N = "7.5";  // normal    mode
 
localparam BTP_O = "1.0";  // overdrive mode
 
`else // default
 
localparam OVD_E = 1'b1;   // overdrive functionality enable
 
localparam BTP_N = "5.0";  // normal    mode
 
localparam BTP_O = "1.0";  // overdrive mode
 
`endif
 
 
 
// port width parameters
 
`ifdef BDW_32
 
localparam BDW   = 32;     // 32bit bus data width
 
`elsif BDW_8
 
localparam BDW   =  8;     //  8bit bus data width
 
`else // default
 
localparam BDW   = 32;     //       bus data width
 
`endif
 
 
 
// number of wires
 
`ifdef OWN
 
localparam OWN   = `OWN;  // number of wires
 
`else
 
localparam OWN   =  3;    // slaves with different timing (min, typ, max)
 
`endif
 
 
 
// computed bus address port width
 
localparam BAW   = (BDW==32) ? 1 : 2;
 
 
 
// clock dividers for normal and overdrive mode
 
// NOTE! must be round integer values
 
`ifdef PRESET_60_05
 
// there is no way to cast a real value into an integer
 
localparam integer CDR_N = 45 - 1;
 
localparam integer CDR_O =  4 - 1;
 
`else
 
localparam integer CDR_N = ((BTP_N == "5.0") ?  5.0 : 7.5 ) * FRQ / 1_000_000 - 1;
 
localparam integer CDR_O = ((BTP_O == "1.0") ?  1.0 : 0.67) * FRQ / 1_000_000 - 1;
 
`endif
 
 
 
// Avalon MM parameters
 
localparam AAW = BAW;    // address width
 
localparam ADW = BDW;    // data width
 
localparam ABW = ADW/8;  // byte enable width
 
 
 
// system_signals
 
reg            clk;  // clock
 
reg            rst;  // reset (asynchronous)
 
// Avalon MM interface
 
reg            avalon_read;
 
reg            avalon_write;
 
reg  [AAW-1:0] avalon_address;
 
reg  [ABW-1:0] avalon_byteenable;
 
reg  [ADW-1:0] avalon_writedata;
 
wire [ADW-1:0] avalon_readdata;
 
wire           avalon_waitrequest;
 
wire           avalon_interrupt;
 
 
 
// Avalon MM local signals
 
wire           avalon_transfer;
 
reg  [BDW-1:0] data;
 
 
 
// onewire
 
wire [OWN-1:0] owr;     // bidirectional
 
wire [OWN-1:0] owr_p;   // output power enable from master
 
wire [OWN-1:0] owr_e;   // output pull down enable from master
 
wire [OWN-1:0] owr_i;   // input into master
 
 
 
// slave conviguration
 
reg            slave_ena;    // slave enable (connect/disconnect from wire)
 
reg      [3:0] slave_sel;    // 1-wire slave select
 
reg            slave_ovd;    // overdrive mode enable
 
reg            slave_dat_r;  // read  data
 
wire [OWN-1:0] slave_dat_w;  // write data
 
 
 
// error checking
 
integer        error;
 
integer        n;
 
 
 
// overdrive enable loop
 
integer        i;
 
 
 
//////////////////////////////////////////////////////////////////////////////
 
// configuration printout and waveforms
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
// request for a dumpfile
 
initial begin
 
  $dumpfile("onewire.vcd");
 
  $dumpvars(0, onewire_tb);
 
end
 
 
 
// print configuration
 
initial begin
 
  $display ("NOTE: Ports : BDW=%0d, BAW=%0d, OWN=%0d", BDW, BAW, OWN);
 
  $display ("NOTE: Clock : FRQ=%3.2fMHz, TCP=%3.2fns", FRQ/1_000_000.0, TCP);
 
  $display ("NOTE: Divide: CDR_E=%0b, CDR_N=%0d, CDR_O=%0d", CDR_E, CDR_N, CDR_O);
 
  $display ("NOTE: Config: OVD_E=%0b, BTP_N=%1.2fus, BTP_O=%1.2fus",
 
                           OVD_E, (CDR_N+1)*1_000_000/FRQ, (CDR_O+1)*1_000_000/FRQ);
 
end
 
 
 
//////////////////////////////////////////////////////////////////////////////
 
// clock and reset
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
// clock generation
 
initial         clk = 1'b1;
 
always #(TCP/2) clk = ~clk;
 
 
 
// reset generation
 
initial begin
 
  rst = 1'b1;
 
  repeat (2) @(posedge clk);
 
  rst = 1'b0;
 
end
 
 
 
//////////////////////////////////////////////////////////////////////////////
 
// Avalon write and read transfers
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
initial begin
 
  // reset error counter
 
  error = 0;
 
 
 
  // Avalon MM interface is idle
 
  avalon_read  = 1'b0;
 
  avalon_write = 1'b0;
 
 
 
  // long delay to skip presence pulse
 
  slave_ena = 1'b0;
 
  #1000_000;
 
 
 
  // set clock divider ratios
 
  if (CDR_E) begin
 
    if (BDW==32) begin
 
      avalon_cycle (1, 1, 4'hf, {   16'h0001,    16'h0001}, data);
 
      avalon_cycle (1, 1, 4'hf, {CDR_O[15:0], CDR_N[15:0]}, data);
 
    end else if (BDW==8) begin
 
      avalon_cycle (1, 2, 1'b1,      8'h01, data);
 
      avalon_cycle (1, 3, 1'b1,      8'h01, data);
 
      avalon_cycle (1, 2, 1'b1, CDR_N[7:0], data);
 
      avalon_cycle (1, 3, 1'b1, CDR_O[7:0], data);
 
    end
 
  end
 
 
 
  // test with slaves with different timing (each slave one one of the wires)
 
  for (slave_sel=0; slave_sel<OWN; slave_sel=slave_sel+1) begin
 
 
 
    // select normal/overdrive mode
 
    //for (slave_ovd=0; slave_ovd<(OVD_E?2:1); slave_ovd=slave_ovd+1) begin
 
    for (i=0; i<(OVD_E?2:1); i=i+1) begin
 
 
 
      slave_ovd = i[0];
 
 
 
      // testbench status message 
 
      $display("NOTE: Loop: speed=%s, ovd=%b, BTP=\"%s\")", (slave_sel==0) ? "typ" : (slave_sel==1) ? "min" : "max", slave_ovd, slave_ovd ? BTP_O : BTP_N);
 
 
 
      // generate a reset pulse
 
      slave_ena   = 1'b0;
 
      slave_dat_r = 1'b1;
 
      avalon_request (16'd0, slave_sel, {slave_ovd, 2'b10});
 
      avalon_polling (8, n);
 
      // expect no response
 
      if (data[0] !== 1'b1) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong presence detect responce ('1' expected).", $time);
 
      end
 
 
 
      // generate a reset pulse
 
      slave_ena   = 1'b1;
 
      slave_dat_r = 1'b1;
 
      avalon_request (16'd0, slave_sel, {slave_ovd, 2'b10});
 
      avalon_polling (8, n);
 
      // expect presence response
 
      if (data[0] !== 1'b0) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong presence detect response ('0' expected).", $time);
 
      end
 
 
 
      // write '0'
 
      slave_ena   = 1'b1;
 
      slave_dat_r = 1'b1;
 
      avalon_request (16'd0, slave_sel, {slave_ovd, 2'b00});
 
      avalon_polling (8, n);
 
      // check if '0' was written into the slave
 
      if (slave_dat_w[slave_sel] !== 1'b0) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong write data for write '0'.", $time);
 
      end
 
      // check if '0' was read from the slave
 
      if (data[0] !== 1'b0) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong read  data for write '0'.", $time);
 
      end
 
 
 
      // write '1', read '1'
 
      slave_ena   = 1'b1;
 
      slave_dat_r = 1'b1;
 
      avalon_request (16'd0, slave_sel, {slave_ovd, 2'b01});
 
      avalon_polling (8, n);
 
      // check if '0' was written into the slave
 
      if (slave_dat_w[slave_sel] !== 1'b1) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong write data for write '1', read '1'.", $time);
 
      end
 
      // check if '1' was read from the slave
 
      if (data[0] !== 1'b1) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong read  data for write '1', read '1'.", $time);
 
      end
 
 
 
      // write '1', read '0'
 
      slave_ena   = 1'b1;
 
      slave_dat_r = 1'b0;
 
      avalon_request (16'd0, slave_sel, {slave_ovd, 2'b01});
 
      avalon_polling (8, n);
 
      // check if '0' was written into the slave
 
      if (slave_dat_w[slave_sel] !== 1'b0) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong write data for write '1', read '0'.", $time);
 
      end
 
      // check if '0' was read from the slave
 
      if (data[0] !== 1'b0) begin
 
        error = error+1;
 
        $display("ERROR: (t=%0t)  Wrong read  data for write '1', read '0'.", $time);
 
      end
 
 
 
    end  // slave_ovd
 
 
 
  end  // slave_sel
 
 
 
  // test power supply on a typical normal mode slave
 
  slave_sel = 0;
 
 
 
  // generate a delay pulse (1ms) with power supply enabled
 
  avalon_request (16'd1, slave_sel, 3'b011);
 
  avalon_polling (1, n);
 
  // check if '1' was read from the slave
 
  if ((data[0] !== 1'b1) & ~slave_ovd) begin
 
    error = error+1;
 
    $display("ERROR: (t=%0t)  Wrong presence detect response (power expected).", $time);
 
  end
 
  // check if power is present
 
  if (owr_p[slave_sel] !== 1'b1) begin
 
    error = error+1;
 
    $display("ERROR: (t=%0t)  Wrong line power state", $time);
 
  end
 
  // check the time to run a delay cycle
 
  if ((n-1)*2 != FRQ/1000) begin
 
    $display("WARNING: (t=%0t)  Non ideal cycle time (%0dus), should be around 1ms.", $time, 2*(n-1)*1_000_000/FRQ);
 
  end
 
 
 
  // generate a idle pulse (0ms) with power supply enabled
 
  avalon_request (16'd1, slave_sel, 3'b111);
 
  avalon_polling (1, n);
 
  // check if power is present
 
  if (owr_p[slave_sel] !== 1'b1) begin
 
    error = error+1;
 
    $display("ERROR: (t=%0t)  Wrong line power state", $time);
 
  end
 
  // check the time to run an idle cycle
 
  if (n>1) begin
 
    $display("ERROR: (t=%0t)  Non ideal idle cycle time, should be around zero.", $time);
 
  end
 
 
 
  // generate a delay pulse and break it with an idle pulse, before it finishes
 
  repeat (10) @(posedge clk);
 
  avalon_request (16'd0, 4'h0, 3'b011);
 
  repeat (10) @(posedge clk);
 
  avalon_request (16'd0, 4'h0, 3'b111);
 
 
 
  // wait a few cycles and finish
 
  repeat (10) @(posedge clk);
 
  $finish();
 
end
 
 
 
// avalon request cycle
 
task avalon_request (
 
  input [15:0] pwr,  // power enable
 
  input  [3:0] sel,  // onewire slave select
 
  input  [2:0] cmd   // command {ovd, rst, dat}
 
);
 
  reg [BDW-1:0] data;  // read data
 
begin
 
  if (BDW==32) begin
 
    avalon_cycle (1, 0, 4'hf, {pwr<<sel, 4'h0, sel, 3'b000, pwr[0], 1'b1, cmd}, data);
 
  end else begin
 
    avalon_cycle (1, 1, 1'b1, {pwr[3:0]<<sel, 2'h0, sel[1:0]}, data);
 
    avalon_cycle (1, 0, 1'b1, {    3'b000, pwr[0], 1'b1, cmd}, data);
 
  end
 
end endtask
 
 
 
// wait for the onewire cycle completion
 
task avalon_polling (
 
  input  integer dly,
 
  output integer n
 
); begin
 
  // set cycle counter to zero
 
  n = 0;
 
  // poll till owr_cyc ends
 
  if (BDW==32) begin
 
    data = 32'h08;
 
    while (data & 32'h08) begin
 
      repeat (dly) @ (posedge clk);
 
      avalon_cycle (0, 0, 4'hf, 32'hxxxx_xxxx, data);
 
      n = n + 1;
 
    end
 
  end else begin
 
    data = 8'h08;
 
    while (data & 8'h08) begin
 
      repeat (dly) @ (posedge clk);
 
      avalon_cycle (0, 0, 1'b1, 8'hxx, data);
 
      n = n + 1;
 
    end
 
  end
 
end endtask
 
 
 
//////////////////////////////////////////////////////////////////////////////
 
// Avalon transfer cycle generation task
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
task automatic avalon_cycle (
 
  input            r_w,  // 0-read or 1-write cycle
 
  input  [AAW-1:0] adr,
 
  input  [ABW-1:0] ben,
 
  input  [ADW-1:0] wdt,
 
  output [ADW-1:0] rdt
 
);
 
begin
 
  if (DEBUG) $display ("Avalon MM cycle start: T=%10tns, %s address=%08x byteenable=%04b writedata=%08x", $time/1000.0, r_w?"write":"read ", adr, ben, wdt);
 
  // start an Avalon cycle
 
  avalon_read       <= ~r_w;
 
  avalon_write      <=  r_w;
 
  avalon_address    <=  adr;
 
  avalon_byteenable <=  ben;
 
  avalon_writedata  <=  wdt;
 
  // wait for waitrequest to be retracted
 
  @ (posedge clk); while (~avalon_transfer) @ (posedge clk);
 
  // end Avalon cycle
 
  avalon_read       <= 1'b0;
 
  avalon_write      <= 1'b0;
 
  // read data
 
  rdt = avalon_readdata;
 
  if (DEBUG) $display ("Avalon MM cycle end  : T=%10tns, readdata=%08x", $time/1000.0, rdt);
 
end
 
endtask
 
 
 
// avalon cycle transfer cycle end status
 
assign avalon_transfer = (avalon_read | avalon_write) & ~avalon_waitrequest;
 
 
 
assign avalon_waitrequest = 1'b0;
 
 
 
//////////////////////////////////////////////////////////////////////////////
 
// RTL instance
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
sockit_owm #(
 
  .OVD_E    (OVD_E),
 
  .CDR_E    (CDR_E),
 
  .BDW      (BDW  ),
 
  .BAW      (BAW  ),
 
  .OWN      (OWN  ),
 
  .BTP_N    (BTP_N),
 
  .BTP_O    (BTP_O),
 
  .CDR_N    (CDR_N),
 
  .CDR_O    (CDR_O)
 
) onewire_master (
 
  // system
 
  .clk      (clk),
 
  .rst      (rst),
 
  // Avalon
 
  .bus_ren  (avalon_read),
 
  .bus_wen  (avalon_write),
 
  .bus_adr  (avalon_address),
 
  .bus_wdt  (avalon_writedata),
 
  .bus_rdt  (avalon_readdata),
 
  .bus_irq  (avalon_interrupt),
 
  // onewire
 
  .owr_p    (owr_p),
 
  .owr_e    (owr_e),
 
  .owr_i    (owr_i)
 
);
 
 
 
// pullup
 
pullup onewire_pullup [OWN-1:0] (owr);
 
 
 
// tristate buffers
 
bufif1 onewire_buffer [OWN-1:0] (owr, owr_p, owr_e | owr_p);
 
 
 
// read back
 
assign owr_i = owr;
 
 
 
//////////////////////////////////////////////////////////////////////////////
 
// Verilog onewire slave models
 
//////////////////////////////////////////////////////////////////////////////
 
 
 
`ifdef OWN
 
 
 
// fast slave device
 
onewire_slave_model onewire_slave [OWN-1:0] (
 
  // configuration
 
  .ena    (slave_ena),
 
  .ovd    (slave_ovd),
 
  .dat_r  (slave_dat_r),
 
  .dat_w  (slave_dat_w),
 
  // 1-wire signal
 
  .owr    (owr)
 
);
 
 
 
`else
 
 
 
// Verilog onewire slave models for normal mode
 
 
 
// typical slave device
 
onewire_slave_model #(
 
  .TS     (30)
 
) onewire_slave_n_typ (
 
  // configuration
 
  .ena    (slave_ena & (slave_ovd==0)),
 
  .ovd    (slave_ovd     ),
 
  .dat_r  (slave_dat_r   ),
 
  .dat_w  (slave_dat_w[0]),
 
  // 1-wire signal
 
  .owr    (owr[0])
 
);
 
 
 
// fast slave device
 
onewire_slave_model #(
 
  .TS     (15 + 0.1)
 
) onewire_slave_n_min (
 
  // configuration
 
  .ena    (slave_ena & (slave_ovd==0)),
 
  .ovd    (slave_ovd     ),
 
  .dat_r  (slave_dat_r   ),
 
  .dat_w  (slave_dat_w[1]),
 
  // 1-wire signal
 
  .owr    (owr[1])
 
);
 
 
 
onewire_slave_model #(
 
  .TS     (60 - 0.1)
 
) onewire_slave_n_max (
 
  // configuration
 
  .ena    (slave_ena & (slave_ovd==0)),
 
  .ovd    (slave_ovd     ),
 
  .dat_r  (slave_dat_r   ),
 
  .dat_w  (slave_dat_w[2]),
 
  // 1-wire signal
 
  .owr    (owr[2])
 
);
 
 
 
// Verilog onewire slave models for overdrive mode
 
 
 
// typical slave device
 
onewire_slave_model #(
 
  .TS     (30)
 
) onewire_slave_o_typ (
 
  // configuration
 
  .ena    (slave_ena & (slave_ovd==1)),
 
  .ovd    (slave_ovd     ),
 
  .dat_r  (slave_dat_r   ),
 
  .dat_w  (slave_dat_w[0]),
 
  // 1-wire signal
 
  .owr    (owr[0])
 
);
 
 
 
// fast slave device
 
onewire_slave_model #(
 
  .TS     (16)
 
) onewire_slave_o_min (
 
  // configuration
 
  .ena    (slave_ena & (slave_ovd==1)),
 
  .ovd    (slave_ovd     ),
 
  .dat_r  (slave_dat_r   ),
 
  .dat_w  (slave_dat_w[1]),
 
  // 1-wire signal
 
  .owr    (owr[1])
 
);
 
 
 
onewire_slave_model #(
 
  .TS     (47)
 
) onewire_slave_o_max (
 
  // configuration
 
  .ena    (slave_ena & (slave_ovd==1)),
 
  .ovd    (slave_ovd     ),
 
  .dat_r  (slave_dat_r   ),
 
  .dat_w  (slave_dat_w[2]),
 
  // 1-wire signal
 
  .owr    (owr[2])
 
);
 
 
 
`endif
 
 
 
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.