Hi,
Attached are the source files for my CheapScope implementation. It was done as my project for an Embedded FPGA class I have taken at UC Santa Cruz extension. It is my first FPGA project so it undoubtedly contains many things than can be done better.
It consists of the basic logic capture piece that is parametrized in terms of the width and depth that it can capture to. It defaults to one block ram on Xilinx Spartan/Virtex-5 parts. Ie, 18-bits wide and 1024 samples. It has a free-running sample capture module plus a simple triggering module.
PicoBlaze (KCPSM-5) and the serial_rx and serial_tx implementation from one of Ken Chapman's demo implementations. It works with 0.9.3 of the OLS at 115200 and the PicoBlaze program will supply zeros if asked for too many samples.
It uses two block rams and something like around 300 slices on a Virtex-5 (almost 2% I think).
My next steps, if I find the time, would be to:
1. Possibly convert it to using Xilinx primitives, although I don't know if I can keep the parametrization.
2. Move the interfacing into Verilog and dispense with KCPSM. This will save one block ram and probably not cost many more slices, but I don't know.
3. Package it better so that it can easily be included in another project
This shows how it used currently (Note that some of this code is probably copyright Ken Chapman or Xilinx and is excerpted to show how it is used):
kcpsm3 processor
( .address(address),
.instruction(instruction),
.port_id(port_id),
.write_strobe(write_strobe),
.out_port(out_port),
.read_strobe(read_strobe),
.in_port(in_port),
.interrupt(interrupt),
.interrupt_ack(interrupt_ack),
.reset(1'b0),
.clk(clk));
cheapscp program_rom
( .address(address),
.instruction(instruction),
.clk(clk));
// The bits that we are going to capture
//
wire [17:0] capture_wires;
// Change this to specify what to capture ...
// These are the address on KCPSM and part of the instruction, which turned
// out to be useful for debugging
assign capture_wires = {address, instruction[17:10]};
wire sample_capture_start;
wire sample_capture_done;
wire sample_cmd_stb;
wire sample_data_stb;
wire [7:0] sample_in_data;
cheapscope_first sample_inst(
.sys_clk(clk),
.rst(1'b0),
.capture_bits(capture_wires),
.capture_start(sample_capture_start),
.capture_done(sample_capture_done),
.cmd(out_port),
.cmd_stb(sample_cmd_stb),
.write_data(out_port),
.write_stb(sample_data_stb),
.read_data(sample_in_data)
);
wire [7:0] capture_status_port;
assign capture_status_port = {6'b000000, sample_capture_start, sample_capture_done};
//--------------------------------------------------------------------------------------------------------------------------------
// KCPSM3 input ports
//--------------------------------------------------------------------------------------------------------------------------------
//
//
// UART FIFO status signals to form a bus
//
assign uart_status_port = {3'b 000,rx_data_present,rx_full,rx_half_full,tx_full,tx_half_full};
//
// The inputs connect via a pipelined multiplexer
// Port 2 is for the LCD. Port 4 is for capture engine command out and status in
// Port 5 is for capture engine data out and data in
//
always @(posedge clk) begin
case(port_id[2:0] )
// read UART status at address 00 hex
3'b000 :
begin
in_port <= uart_status_port;
end
// read UART receive data at address 01 hex
3'b001 :
begin
in_port <= rx_data;
end
// The Capture status
3'b100 :
begin
in_port <= capture_status_port;
end
// The read port on the capture engine
3'b101 :
begin
in_port <= sample_in_data;
end
// Don't care used for all other addresses to ensure minimum logic implementation
default :
begin
in_port <= 8'b XXXXXXXX;
end
endcase
//--------------------------------------------------------------------------------------------------------------------------------
// KCPSM3 output ports
//--------------------------------------------------------------------------------------------------------------------------------
//
// adding the output registers to the clock processor
always @(posedge clk) begin
if(write_strobe == 1'b1) begin
// Alarm register at address 00 hex with data bit0 providing control -- ignored!
case (port_id[2:0])
3'b000: begin
//ld_r <= out_port[3:0];
end
3'b010:
begin // The LCD is on port 2 ... see below
if (lcd_state == LCD_IDLE) begin
lcd_val <= out_port;
lcd_start <= 1'b1;
end
end
default:
begin
lcd_start <= 1'b0;
end
endcase
end
if (lcd_state != LCD_IDLE) begin
lcd_start <= 1'b0;
end
end
assign sample_cmd_stb = write_strobe & (port_id[2:0] == 3'b100);
assign sample_data_stb = write_strobe & (port_id[2:0] == 3'b101);
I have not bothered showing the UART rx and tx instances nor the clock generator ... they can be obtained elsewhere.
I will upload a screen shot of the OLS client with a grab of the capture as well as:
1. cheapscope_simple.v, the logic capture engine
2. byte_to_reg.v, something I seemed to need to make some things parametrized
3. cheapscp.psm
Hmm, it seems that I cannot attach raw Verilog files so I will have to package them together as a zip file or something.
Attached are the files I said I would add. They are in a zip file.
No, it is not.
I am in no way affiliated with Xilinx.
I just took a class that was run by a guy from Xilinx and he suggested this as a project idea and I thought I would give it a go.
It is a very simple subset of the ChipScope functionality, I believe (although I have not used ChipScope).
The name is a joke on Xilinx' ChipScope.
I do hope to improve it over time, though, but as it is my first FPGA project, I am sure that it has many flaws.
My first improvement will be to turn it into a stand-alone module. I have discussed the issues of reusing the UART pieces supplied by Ken Chapman with our instructor, and he suggests that there are no such issues.
What I would like to do is implement something like:
module cheapscope_simple(clk, signals, tx, rx)
so that all you have to do is instantiate just that. At the moment it is a bit of a dogs breakfast. You should then be able to specify parameters like the capture width, capture depth (size of RAMS), clock frequency and UART speed ... currently only capture width and depth are parameters, but I realized last night in getting it to work on the instructor's Spartan-3 board from Digilent that the clock frequency to UART bit-rate generator needed to be changed.
This will probably re-use the rx and tx pieces from Ken Chapman that use Xilinx primitives, but it could also be re-implemented with open versions of the rx and tx modules.
In discussion last night we concluded that ChipScope might use JTAG to communicate with the other tools, but for compatibility with the OLS client, it is better to use serial communications.