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

Subversion Repositories wbscope

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /wbscope
    from Rev 5 to Rev 6
    Reverse comparison

Rev 5 → Rev 6

/trunk/rtl/wbscopc.v
5,20 → 5,27
// Project: FPGA Library of Routines
//
// Purpose: This scope is identical in function to the wishbone scope
// found in wbscope, save that the output is compressed and that
// (as a result) it can only handle recording 31 bits at a time.
// This allows the top bit to indicate an 'address'.
// found in wbscope, save that the output is compressed and that (as a
// result) it can only handle recording 31 bits at a time. This allows
// the top bit to indicate an 'address difference'. Okay, there's
// another difference as well: this version only works in a synchronous
// fashion with the clock from the WB bus. You cannot have a separate
// bus and data clock.
//
// Reading/decompressing the output of this scope works in this
// fashion: clear a memory. Then, once the scope has stopped,
// 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
// memory location and increment the memory address after writing.
// Reading/decompressing the output of this scope works in this fashion:
// 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
// discussion purposes. While wbscope.v works and works well by itself,
// this compressed scope has a fundamental flaw that I have yet to fix:
// The first values out of the scope take place at an unknown address.
// this compressed scope has a couple of fundamental flaw that I have
// 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,
// even if the scope was skipping values to a new address at the time.
32,6 → 39,15
// not because it runs nor because I have recognized that it has any
// 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.
// Gisselquist Tecnology, LLC
//
83,20 → 99,43
 
// Let's first see how far we can get by cheating. We'll use the
// 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;
assign lcl_reset = (i_wb_cyc)&&(i_wb_stb)&&(~i_wb_addr)&&(i_wb_we)
&&(~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;
initial ck_addr = 0;
always @(posedge i_clk)
if (lcl_reset)
if ((lcl_reset)||((i_ce)&&(i_data != lst_data)))
ck_addr <= 0;
else if (&ck_addr)
; // Saturated (non-overflowing) address diff
else
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_adr = 1'b1;
initial imm_adr = 1'b1;
116,12 → 155,16
lst_adr <= imm_adr;
lst_dat <= i_data;
end else begin
imm_val <= ck_addr;
imm_val <= ck_addr; // Minimum value here is '1'
imm_adr <= 1'b1;
lst_val <= imm_val;
lst_adr <= imm_adr;
end
 
//
// Here's where we suppress writing pairs of address words to the
// scope at once.
//
reg r_ce;
reg [(BUSW-1):0] r_data;
initial r_ce = 1'b0;
132,9 → 175,11
? { lst_adr, lst_val }
: { 1'b0, i_data };
 
 
wbscope #(.SYNCHRONOUS(1),
.LGMEM(LGMEM),
//
// Call the regular wishbone scope to do all of our real work, now
// that we've compressed the input.
//
wbscope #(.SYNCHRONOUS(1), .LGMEM(LGMEM),
.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,
o_wb_ack, o_wb_stall, o_wb_data, o_interrupt);
/trunk/doc/spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/trunk/doc/src/spec.tex
86,7 → 86,7
 
When I then needed to make the project run in real-time, as opposed to the
manually stepped approach, I generated a scope like this one. I had already
bench tested the components on the hardware itself. Thu, testing and
bench tested the components on the hardware itself. Thus, testing and
development continued on the hardware, and the scope helped me see what was
going right or wrong. The great advantage of the approach was that, at the
end of the project, I didn't need to do any hardware in the loop testing.
160,27 → 160,30
 
Let's go through that list again. First, before using the scope, the holdoff
needs to be set. The scope is designed so that setting the scope control value
to the holdoff alone will reset the scope from whatever condition it was in,
to the holdoff alone, with all other bits set to zero, will reset the scope
from whatever condition it was in,
freeing it to run. Once running, then upon every clock enabled clock, one
sample of data is read into the scope and recorded. Once every memory value
is filled, the scope has been {\tt PRIMED}. Once the scope has been
{\tt PRIMED}, it will then be responsive to its trigger. Should the trigger be
active on a clock--enabled input, the scope will then be {\tt TRIGGERED}. It
active on an input clock with the clock--enable line set, the scope will then
be {\tt TRIGGERED}. It
will then count for the number of clocks in the holdoff before stopping
collection, placing it in the {\tt STOPPED} state. (Don't change the holdoff
during between triggered and stopped, or it may stop at some other non--holdoff
value!) If the holdoff is zero, the last sample in the buffer will be the
sample containing the trigger. Likewise if the holdoff is one less than the
size of the memory, the first sample in the buffer will be the one containing
the trigger.
collection, placing it in the {\tt STOPPED} state. \footnote{You can even
change the holdoff while the scope is running by writing a new holdoff value
together with setting the {\tt RESET\_n} bit of the control register. However,
if you do this after the core has triggered it may stop at some other
non--holdoff value!} If the holdoff is zero, the last sample in the buffer
will be the sample containing the trigger. Likewise if the holdoff is one
less than the size of the memory, the first sample in the buffer will be the
one containing the trigger.
There are two further commands that will affect the operation of the scope. The
first is the {\tt MANUAL} trigger command/bit. This bit may be set by writing
the holdoff to the control register while setting this bit high. This will
cause the scope to trigger immediately. If coupled with a {\tt RESET} command,
that is if the {\tt RESET\_n} bit isn't also set, then recording will start
at the beginning and the scope will first wait until its {\tt PRIMED} state
before the manual trigger takes effect.
cause the scope to trigger as soon as it is primed. If the {\tt RESET\_n}
bit is also set so as to prevent an internal reset, and if the scope was already
primed, then manual trigger command will cause it to trigger immediately.
 
The last command that can affect the operation of the scope is the {\tt DISABLE}
command/bit in the control register. Setting this bit will prevent the scope
192,10 → 195,11
reasonable amount of time.
 
So, in summary, to use this scope you first set the holdoff value in the
control register. Second, you wait until the scope has been {\tt TRIGGERED} and
stopped. Finally, you read from the data register once for every memory value
in the buffer and you can then sit back, relax, and study what took place
within the FPGA.
control register. Second, you wait until the scope has been {\tt TRIGGERED}
and {\tt STOPPED}. Finally, you read from the data register once for every
memory value in the buffer and you can then sit back, relax, and study what
took place within the FPGA. Additional modes allow you to manually trigger
the scope, or to disable the automatic trigger entirely.
\chapter{Registers}
 
331,7 → 335,11
registers become 32--bit reads and writes to this interface. You may also wish
to note that the scope supports pipeline reads from the data port, to speed
up reading the results out.
 
What this table doesn't show is that all accesses to the port take a single
clock. That is, if the {\tt i\_wb\_stb} line is high on one clock, the
{\tt i\_wb\_ack} line will be high the next. Further, the {\tt o\_wb\_stall}
line is tied to zero.
\chapter{IO Ports}
 
The ports are listed in Table.~\ref{tbl:ioports}.

powered by: WebSVN 2.1.0

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