Line 34... |
Line 34... |
// are (1<<LGMEMLEN) items in the memory, and that the trigger took place
|
// are (1<<LGMEMLEN) items in the memory, and that the trigger took place
|
// on the last item of memory ... so that portion of this compressed
|
// on the last item of memory ... so that portion of this compressed
|
// scope is still to be defined.
|
// scope is still to be defined.
|
//
|
//
|
// 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 well 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
|
// 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
|
// PS/2 interface, or even the 16x2 LCD interface, it is often true
|
// that things change _very_ slowly. They could change so slowly that
|
// that things change _very_ slowly. They could change so slowly that
|
Line 46... |
Line 46... |
// a working scope, by only capturing the changes. You'll still need
|
// a working scope, by only capturing the changes. You'll still need
|
// to figure out (after the fact) when the trigge took place. Perhaps
|
// 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
|
// you'll wish to add the trigger as another data line, so you can find
|
// when it took place in your own data?
|
// when it took place in your own data?
|
//
|
//
|
|
// Okay, I take that back twice: I'm finding this compressed scope very
|
|
// valuable for evaluating the timing associated with a GPS PPS and
|
|
// associated NMEA stream. I need to collect over a seconds worth of
|
|
// data, and I don't have enough memory to handle one memory value per
|
|
// clock, yet I still want to know exactly when the GPS PPS goes high,
|
|
// when it goes low, when I'm adjusting my clock, and when the clock's
|
|
// PPS output goes high. Did I synchronize them well? Oh, and when does
|
|
// the NMEA time string show up when compared with the PPS? All of those
|
|
// are valuable, but could never be done if the scope wasn't compressed.
|
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Tecnology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
// Copyright (C) 2015, Gisselquist Technology, LLC
|
//
|
//
|
Line 79... |
Line 89... |
//
|
//
|
module wbscopc(i_clk, i_ce, i_trigger, i_data,
|
module wbscopc(i_clk, i_ce, i_trigger, i_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_wb_ack, o_wb_stall, o_wb_data,
|
o_interrupt);
|
o_interrupt);
|
parameter LGMEM = 5'd10, BUSW = 32, SYNCHRONOUS=1;
|
parameter LGMEM = 5'd10, NELM=32, BUSW = 32, SYNCHRONOUS=1;
|
// The input signals that we wish to record
|
// The input signals that we wish to record
|
input i_clk, i_ce, i_trigger;
|
input i_clk, i_ce, i_trigger;
|
input [(BUSW-2):0] i_data;
|
input [(NELM-1):0] i_data;
|
// The WISHBONE bus for reading and configuring this scope
|
// The WISHBONE bus for reading and configuring this scope
|
input i_wb_clk, i_wb_cyc, i_wb_stb, i_wb_we;
|
input i_wb_clk, i_wb_cyc, i_wb_stb, i_wb_we;
|
input i_wb_addr; // One address line only
|
input i_wb_addr; // One address line only
|
input [(BUSW-1):0] i_wb_data;
|
input [(BUSW-1):0] i_wb_data;
|
output wire o_wb_ack, o_wb_stall;
|
output wire o_wb_ack, o_wb_stall;
|
Line 115... |
Line 125... |
//
|
//
|
// To implement this, we set our 'address' to zero any time the
|
// To implement this, we set our 'address' to zero any time the
|
// data changes, but increment it on all other clocks. Should the
|
// data changes, but increment it on all other clocks. Should the
|
// address difference get to our maximum value, we let it saturate
|
// address difference get to our maximum value, we let it saturate
|
// rather than overflow.
|
// rather than overflow.
|
reg [(BUSW-2):0] ck_addr, lst_dat;
|
reg [(BUSW-2):0] ck_addr;
|
|
reg [(NELM-1):0] lst_dat;
|
initial ck_addr = 0;
|
initial ck_addr = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if ((lcl_reset)||((i_ce)&&(i_data != lst_dat)))
|
if ((lcl_reset)||((i_ce)&&(i_data != lst_dat)))
|
ck_addr <= 0;
|
ck_addr <= 0;
|
else if (&ck_addr)
|
else if (&ck_addr)
|
Line 143... |
Line 154... |
begin
|
begin
|
imm_val <= 31'h0;
|
imm_val <= 31'h0;
|
imm_adr <= 1'b1;
|
imm_adr <= 1'b1;
|
lst_val <= 31'h0;
|
lst_val <= 31'h0;
|
lst_adr <= 1'b1;
|
lst_adr <= 1'b1;
|
lst_dat <= 31'b0;
|
lst_dat <= 0;
|
end else if ((i_ce)&&(i_data != lst_dat))
|
end else if ((i_ce)&&(i_data != lst_dat))
|
begin
|
begin
|
imm_val <= i_data;
|
imm_val <= { {(BUSW-1-NELM){1'b0}}, i_data };
|
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
|
Line 170... |
Line 181... |
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 };
|
: { {(32 - NELM){1'b0}}, i_data };
|
|
|
|
|
|
//
|
|
// The trigger needs some extra attention, in order to keep triggers
|
|
// that happen between events from being ignored.
|
|
//
|
|
wire w_trigger;
|
|
assign w_trigger = (r_trigger)||(i_trigger);
|
|
|
|
reg r_trigger;
|
|
initial r_trigger = 1'b0;
|
|
always @(posedge i_clk)
|
|
if (lcl_reset)
|
|
r_trigger <= 1'b0;
|
|
else
|
|
r_trigger <= w_trigger;
|
|
|
//
|
//
|
// Call the regular wishbone scope to do all of our real work, now
|
// Call the regular wishbone scope to do all of our real work, now
|
// that we've compressed the input.
|
// that we've compressed the input.
|
//
|
//
|
wbscope #(.SYNCHRONOUS(1), .LGMEM(LGMEM),
|
wbscope #(.SYNCHRONOUS(1), .LGMEM(LGMEM),
|
.BUSW(BUSW)) cheatersscope(i_clk, r_ce, i_trigger, r_data,
|
.BUSW(BUSW)) cheatersscope(i_clk, r_ce, w_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
|