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

Subversion Repositories wbscope

[/] [wbscope/] [trunk/] [rtl/] [wbscopc.v] - Diff between revs 3 and 6

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 3 Rev 6
Line 3... Line 3...
// Filename:    wbscopc.v
// Filename:    wbscopc.v
//
//
// Project:     FPGA Library of Routines
// Project:     FPGA Library of Routines
//
//
// Purpose:     This scope is identical in function to the wishbone scope
// Purpose:     This scope is identical in function to the wishbone scope
//              found in wbscope, save that the output is compressed and that
//      found in wbscope, save that the output is compressed and that (as a
//              (as a result) it can only handle recording 31 bits at a time.
//      result) it can only handle recording 31 bits at a time.  This allows
//              This allows the top bit to indicate an 'address'. 
//      the top bit to indicate an 'address difference'.   Okay, there's 
//
//      another difference as well: this version only works in a synchronous
//              Reading/decompressing the output of this scope works in this
//      fashion with the clock from the WB bus.  You cannot have a separate
//              fashion: clear a memory.  Then, once the scope has stopped,
//      bus and data clock.
//              read from the port.  If it's an address (high bit set), then
//
//              jump to that address.  If it's not, then write into that
//      Reading/decompressing the output of this scope works in this fashion:
//              memory location and increment the memory address after writing.
//      Once the scope has stopped, read from the port.  Any time the high
 
//      order bit is set, the other 31 bits tell you how many times to repeat
 
//      the last value.  If the high order bit is not set, then the value
 
//      is a new data value.
//
//
//      I've provided this version of a compressed scope to OpenCores for
//      I've provided this version of a compressed scope to OpenCores for
//      discussion purposes.  While wbscope.v works and works well by itself,
//      discussion purposes.  While wbscope.v works and works well by itself,
//      this compressed scope has a fundamental flaw that I have yet to fix:
//      this compressed scope has a couple of fundamental flaw that I have
//      The first values out of the scope take place at an unknown address.
//      yet to fix.  One of them is that it is impossible to know when the
 
//      trigger took place.  The second problem is that it may be impossible
 
//      to know the state of the scope at the beginning of the buffer--should
 
//      the buffer begin with an address difference value instead of a data
 
//      value.
//
//
//      Ideally, the first item read out of the scope should be a data value,
//      Ideally, the first item read out of the scope should be a data value,
//      even if the scope was skipping values to a new address at the time.
//      even if the scope was skipping values to a new address at the time.
//      If it was in the middle of a skip, the next item out of the scope
//      If it was in the middle of a skip, the next item out of the scope
//      should be the skip length.  This, though, violates the rule that there
//      should be the skip length.  This, though, violates the rule that there
Line 30... Line 37...
//
//
//      Like I said, this version is placed here for discussion purposes,
//      Like I said, this version is placed here for discussion purposes,
//      not because it runs nor because I have recognized that it has any
//      not because it runs nor because I have recognized that it has any
//      particular value (yet).
//      particular value (yet).
//
//
 
//      Well, I take that back.  When dealing with an interface such as the
 
//      PS/2 interface, or even the 16x2 LCD interface, it is often true
 
//      that things change _very_ slowly.  They could change so slowly that
 
//      the other approach to the scope doesn't work.  This then gives you
 
//      a working scope, by only capturing the changes.  You'll still need
 
//      to figure out (after the fact) when the trigge took place.  Perhaps
 
//      you'll wish to add the trigger as another data line, so you can find
 
//      when it took place in your own data?
 
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Tecnology, LLC
//              Gisselquist Tecnology, LLC
//
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
//
Line 81... Line 97...
        output  wire                    o_interrupt;
        output  wire                    o_interrupt;
 
 
 
 
        // Let's first see how far we can get by cheating.  We'll use the
        // Let's first see how far we can get by cheating.  We'll use the
        // wbscope program, and suffer a lack of several features
        // wbscope program, and suffer a lack of several features
 
 
 
        // When is the full scope reset?  Capture that reset bit from any
 
        // write.
        wire    lcl_reset;
        wire    lcl_reset;
        assign  lcl_reset = (i_wb_cyc)&&(i_wb_stb)&&(~i_wb_addr)&&(i_wb_we)
        assign  lcl_reset = (i_wb_cyc)&&(i_wb_stb)&&(~i_wb_addr)&&(i_wb_we)
                                &&(~i_wb_data[31]);
                                &&(~i_wb_data[31]);
 
 
 
        // A big part of this scope is the 'address' of any particular
 
        // data value.  As of this current version, the 'address' changed
 
        // in definition from an absolute time (which had all kinds of
 
        // problems) to a difference in time.  Hence, when the address line
 
        // is high on decompression, the 'address' field will record an
 
        // address difference.
 
        //
 
        // To implement this, we set our 'address' to zero any time the
 
        // data changes, but increment it on all other clocks.  Should the
 
        // address difference get to our maximum value, we let it saturate
 
        // rather than overflow.
        reg     [(BUSW-2):0]     ck_addr;
        reg     [(BUSW-2):0]     ck_addr;
        initial ck_addr = 0;
        initial ck_addr = 0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (lcl_reset)
                if ((lcl_reset)||((i_ce)&&(i_data != lst_data)))
                        ck_addr <= 0;
                        ck_addr <= 0;
 
                else if (&ck_addr)
 
                        ;       // Saturated (non-overflowing) address diff
                else
                else
                        ck_addr <= ck_addr + 1;
                        ck_addr <= ck_addr + 1;
 
 
        reg     imm_adr, lst_adr;
        //
        reg     [(BUSW-2):0]     lst_dat, lst_val, imm_val;
        // To do our compression, we keep track of two registers: the most
 
        // recent data to the device (imm_ prefix) and the data from one
 
        // clock ago.  This allows us to suppress writes to the scope which
 
        // would otherwise be two address writes in a row.
 
        reg     imm_adr, lst_adr; // Is this an address (1'b1) or data value?
 
        reg     [(BUSW-2):0]     lst_dat, // The data associated with t-1
 
                                lst_val, // Data for the scope, delayed by one
 
                                imm_val; // Data to write to the scope
        initial lst_dat = 0;
        initial lst_dat = 0;
        initial lst_adr = 1'b1;
        initial lst_adr = 1'b1;
        initial imm_adr = 1'b1;
        initial imm_adr = 1'b1;
        always @(posedge i_clk)
        always @(posedge i_clk)
                if (lcl_reset)
                if (lcl_reset)
Line 114... Line 153...
                        imm_adr <= 1'b0;
                        imm_adr <= 1'b0;
                        lst_val <= imm_val;
                        lst_val <= imm_val;
                        lst_adr <= imm_adr;
                        lst_adr <= imm_adr;
                        lst_dat <= i_data;
                        lst_dat <= i_data;
                end else begin
                end else begin
                        imm_val <= ck_addr;
                        imm_val <= ck_addr; // Minimum value here is '1'
                        imm_adr <= 1'b1;
                        imm_adr <= 1'b1;
                        lst_val <= imm_val;
                        lst_val <= imm_val;
                        lst_adr <= imm_adr;
                        lst_adr <= imm_adr;
                end
                end
 
 
 
        //
 
        // Here's where we suppress writing pairs of address words to the
 
        // scope at once.
 
        //
        reg                     r_ce;
        reg                     r_ce;
        reg     [(BUSW-1):0]     r_data;
        reg     [(BUSW-1):0]     r_data;
        initial                 r_ce = 1'b0;
        initial                 r_ce = 1'b0;
        always @(posedge i_clk)
        always @(posedge i_clk)
                r_ce <= (~lst_adr)||(~imm_adr);
                r_ce <= (~lst_adr)||(~imm_adr);
        always @(posedge i_clk)
        always @(posedge i_clk)
                r_data <= ((~lst_adr)||(~imm_adr))
                r_data <= ((~lst_adr)||(~imm_adr))
                        ? { lst_adr, lst_val }
                        ? { lst_adr, lst_val }
                        : { 1'b0, i_data };
                        : { 1'b0, i_data };
 
 
 
        //
        wbscope #(.SYNCHRONOUS(1),
        // Call the regular wishbone scope to do all of our real work, now
                .LGMEM(LGMEM),
        // that we've compressed the input.
 
        //
 
        wbscope #(.SYNCHRONOUS(1), .LGMEM(LGMEM),
                .BUSW(BUSW))    cheatersscope(i_clk, r_ce, i_trigger, r_data,
                .BUSW(BUSW))    cheatersscope(i_clk, r_ce, i_trigger, r_data,
                i_wb_clk, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                i_wb_clk, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                o_wb_ack, o_wb_stall, o_wb_data, o_interrupt);
                o_wb_ack, o_wb_stall, o_wb_data, o_interrupt);
endmodule
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.