logic analyzer appears to kinda work in simulation. buggy, but working!

This commit is contained in:
Fischer Moseley 2023-04-02 13:54:34 -04:00
parent 839bd4f8e4
commit af295ead51
6 changed files with 181 additions and 140 deletions

View File

@ -41,9 +41,10 @@ class UARTInterface:
if "verbose" in config:
self.verbose = config["verbose"]
# open port
import serial
self.ser = serial.Serial(self.port, self.baudrate)
def open_port_if_not_alredy_open(self):
if not hasattr(self, "ser"):
import serial
self.ser = serial.Serial(self.port, self.baudrate)
def autodetect_port(self):
# as far as I know the FT2232 is the only chip used on the icestick/digilent boards, so just look for that
@ -65,6 +66,8 @@ class UARTInterface:
return rd[0].device if rd[0].location > rd[1].location else rd[1].device
def read_register(self, addr):
self.open_port_if_not_alredy_open()
# request from the bus
addr_str = '{:04X}'.format(addr)
request = f"M{addr_str}\r\n".encode('ascii')
@ -91,6 +94,8 @@ class UARTInterface:
return data
def write_register(self, addr, data):
self.open_port_if_not_alredy_open()
# request from the bus
addr_str = '{:04X}'.format(addr)
data_str = '{:04X}'.format(data)

View File

@ -8,6 +8,7 @@ module la_fsm(
input wire [$clog2(SAMPLE_DEPTH):0] fifo_size,
output reg fifo_acquire,
output reg fifo_pop,
output reg fifo_clear,
// input port
input wire [15:0] addr_i,
@ -28,10 +29,11 @@ module la_fsm(
// state machine
localparam IDLE = 0;
localparam MOVE_TO_POSITION = 1;
localparam IN_POSITION = 2;
localparam FILLING_BUFFER = 3;
localparam FILLED = 4;
localparam START_CAPTURE = 1;
localparam MOVE_TO_POSITION = 2;
localparam IN_POSITION = 3;
localparam FILLING_BUFFER = 4;
localparam FILLED = 5;
reg [3:0] state;
reg signed [15:0] trigger_loc;
@ -76,7 +78,14 @@ module la_fsm(
present_loc <= (trigger_loc < 0) ? trigger_loc : 0;
end
else if(state == START_CAPTURE) begin
// perform whatever setup is needed before starting the next capture
fifo_clear <= 1;
state <= MOVE_TO_POSITION;
end
else if(state == MOVE_TO_POSITION) begin
fifo_clear <= 0;
// if trigger location is negative or zero,
// then we're already in position
if(trigger_loc <= 0) state <= IN_POSITION;

View File

@ -36,6 +36,7 @@ module logic_analyzer(
.fifo_size(fifo_size),
.fifo_acquire(fifo_acquire),
.fifo_pop(fifo_pop),
.fifo_clear(fifo_clear),
.addr_i(addr_i),
.wdata_i(wdata_i),
@ -59,6 +60,7 @@ module logic_analyzer(
reg [$clog2(SAMPLE_DEPTH):0] fifo_size;
reg fifo_acquire;
reg fifo_pop;
reg fifo_clear;
// trigger block
@ -98,6 +100,7 @@ module logic_analyzer(
.acquire(fifo_acquire),
.pop(fifo_pop),
.size(fifo_size),
.clear(fifo_clear),
// probes
.larry(larry),

View File

@ -7,7 +7,8 @@ module sample_mem(
// fifo
input wire acquire,
input wire pop,
output wire [AW:0] size,
output wire [BRAM_ADDR_WIDTH:0] size,
input wire clear,
// probes
input wire larry,
@ -31,9 +32,10 @@ module sample_mem(
parameter BASE_ADDR = 0;
parameter SAMPLE_DEPTH = 0;
localparam BRAM_ADDR_WIDTH = $clog2(SAMPLE_DEPTH);
// bus controller
reg [$clog2(SAMPLE_DEPTH):0] bram_read_addr;
reg [BRAM_ADDR_WIDTH-1:0] bram_read_addr;
reg [15:0] bram_read_data;
always @(*) begin
@ -91,7 +93,7 @@ module sample_mem(
.rsta(1'b0),
.ena(1'b1),
.addra(bram_read_addr),
.dina(),
.dina(16'b0),
.wea(1'b0),
.regcea(1'b1),
.douta(bram_read_data),
@ -100,24 +102,23 @@ module sample_mem(
.clkb(clk),
.rstb(1'b0),
.enb(1'b1),
.addrb(write_pointer),
.dinb({larry, curly, moe, shemp}),
.addrb(write_pointer[BRAM_ADDR_WIDTH-1:0]),
.dinb({9'b0, larry, curly, moe, shemp}),
.web(acquire),
.regceb(1'b1),
.doutb());
// fifo
localparam AW = $clog2(SAMPLE_DEPTH);
reg [AW:0] write_pointer = 0;
reg [AW:0] read_pointer = 0;
reg [BRAM_ADDR_WIDTH:0] write_pointer = 0;
reg [BRAM_ADDR_WIDTH:0] read_pointer = 0;
assign size = write_pointer - read_pointer;
always @(posedge clk) begin
if (acquire) write_pointer <= write_pointer + 1'd1;
if (pop) read_pointer <= read_pointer + 1'd1;
if (clear) read_pointer <= write_pointer;
if (acquire && size < SAMPLE_DEPTH) write_pointer <= write_pointer + 1'd1;
if (pop && size > 0) read_pointer <= read_pointer + 1'd1;
end
endmodule

View File

@ -33,8 +33,8 @@ module trigger_block(
// - each probe gets an operation and a compare register
// - at the end we OR them all together. along with any custom probes the user specs
reg [3:0] larry_trigger_op;
reg larry_trigger_arg;
reg [3:0] larry_trigger_op = 0;
reg larry_trigger_arg = 0;
reg larry_trig;
trigger #(.INPUT_WIDTH(1)) larry_trigger(
.clk(clk),
@ -44,8 +44,8 @@ module trigger_block(
.arg(larry_trigger_arg),
.trig(larry_trig));
reg [3:0] curly_trigger_op;
reg curly_trigger_arg;
reg [3:0] curly_trigger_op = 0;
reg curly_trigger_arg = 0;
reg curly_trig;
trigger #(.INPUT_WIDTH(1)) curly_trigger(
.clk(clk),
@ -56,8 +56,8 @@ module trigger_block(
.trig(curly_trig));
reg [3:0] moe_trigger_op;
reg moe_trigger_arg;
reg [3:0] moe_trigger_op = 0;
reg moe_trigger_arg = 0;
reg moe_trig;
trigger #(.INPUT_WIDTH(1)) moe_trigger(
.clk(clk),
@ -67,8 +67,8 @@ module trigger_block(
.arg(moe_trigger_arg),
.trig(moe_trig));
reg [3:0] shemp_trigger_op;
reg [3:0] shemp_trigger_arg;
reg [3:0] shemp_trigger_op = 0;
reg [3:0] shemp_trigger_arg = 0;
reg shemp_trig;
trigger #(.INPUT_WIDTH(4)) shemp_trigger(
.clk(clk),
@ -78,8 +78,7 @@ module trigger_block(
.arg(shemp_trigger_arg),
.trig(shemp_trig));
reg triggered;
assign triggered = larry_trig || curly_trig || moe_trig || shemp_trig;
assign trig = larry_trig || curly_trig || moe_trig || shemp_trig;
// perform register operations
always @(posedge clk) begin

View File

@ -3,6 +3,48 @@
`define CP 10
`define HCP 5
task read_reg (
input [15:0] addr,
output [15:0] data
);
logic_analyzer_tb.tb_la_addr = addr;
logic_analyzer_tb.tb_la_rw = 0;
logic_analyzer_tb.tb_la_valid = 1;
#`CP
logic_analyzer_tb.tb_la_valid = 0;
while (!logic_analyzer_tb.la_tb_valid) #`CP;
data = logic_analyzer_tb.la_tb_rdata;
endtask
task write_reg(
input [15:0] addr,
input [15:0] data
);
logic_analyzer_tb.tb_la_addr = addr;
logic_analyzer_tb.tb_la_wdata = data;
logic_analyzer_tb.tb_la_rw = 1;
logic_analyzer_tb.tb_la_valid = 1;
#`CP
logic_analyzer_tb.tb_la_valid = 0;
while (!logic_analyzer_tb.la_tb_valid) #`CP;
endtask
task read_all_reg();
for(int i = 0; i < (logic_analyzer_tb.la.sample_mem.BASE_ADDR + logic_analyzer_tb.la.SAMPLE_DEPTH); i++) begin
if(i == logic_analyzer_tb.la.fsm.BASE_ADDR) $display(" -> FSM MEMORY");
if(i == logic_analyzer_tb.la.trig_blk.BASE_ADDR) $display(" -> TRIG BLK MEMORY");
if(i == logic_analyzer_tb.la.sample_mem.BASE_ADDR) $display(" -> SAMPLE MEM MEMORY");
read_reg(i, logic_analyzer_tb.read_value);
$display(" -> addr: 0x%h rdata: 0x%b", i, logic_analyzer_tb.read_value);
end
endtask
module logic_analyzer_tb;
// boilerplate
@ -58,6 +100,8 @@ module logic_analyzer_tb;
clk = !clk;
end
reg [15:0] read_value;
initial begin
$dumpfile("logic_analyzer_tb.vcd");
$dumpvars(0, logic_analyzer_tb);
@ -83,60 +127,29 @@ module logic_analyzer_tb;
$display("\n=== test 1: read state register ===");
test_num = 1;
tb_la_addr = 0;
tb_la_valid = 1;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
$display(" -> read 0x%h from state reg (addr 0x0000)", la_tb_rdata);
read_reg(0, read_value);
$display(" -> read 0x%h from state reg (addr 0x0000)", read_value);
#(10*`CP);
/* ==== Test 1 End ==== */
/* ==== Test 2 Begin ==== */
$display("\n=== test 2: write to state register and verify ===");
test_num = 2;
// write
tb_la_addr = 0;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = 5;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
write_reg(0, 5);
$display(" -> wrote 0x0005 to state reg (addr 0x0000)");
// read
tb_la_valid = 1;
tb_la_rw = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
$display(" -> read 0x%h from state reg (addr 0x0000)", la_tb_rdata);
read_reg(0, read_value);
$display(" -> read 0x%h from state reg (addr 0x0000)", read_value);
// write
tb_la_addr = 0;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
write_reg(0, 0);
$display(" -> wrote 0x0000 to state reg (addr 0x0000)");
// read
tb_la_valid = 1;
tb_la_rw = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
read_reg(0, read_value);
$display(" -> read 0x%h from state reg (addr 0x0000)", la_tb_rdata);
#(10*`CP);
/* ==== Test 2 End ==== */
@ -146,42 +159,17 @@ module logic_analyzer_tb;
$display("\n=== test 3: write to trigger_loc register and verify ===");
test_num = 3;
// write
tb_la_addr = 1;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = -16'sd69;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
write_reg(1, -16'sd69);
$display(" -> wrote -0d69 to trigger_loc reg (addr 0x0001)");
// read
tb_la_valid = 1;
tb_la_rw = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
$display(" -> read 0d%d from trigger_loc reg (addr 0x0001)", $signed(la_tb_rdata));
read_reg(1, read_value);
$display(" -> read 0d%d from trigger_loc reg (addr 0x0001)", $signed(read_value));
// write
tb_la_addr = 1;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
write_reg(1, 0);
$display(" -> wrote 0x0000 to trigger_loc reg (addr 0x0001)");
// read
tb_la_valid = 1;
tb_la_rw = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
$display(" -> read 0x%h from trigger_loc reg (addr 0x0001)", $signed(la_tb_rdata));
read_reg(1, read_value);
$display(" -> read 0x%h from trigger_loc reg (addr 0x0001)", $signed(read_value));
#(10*`CP);
/* ==== Test 3 End ==== */
@ -192,24 +180,11 @@ module logic_analyzer_tb;
$display("\n=== test 4: configure larry_op for equality and verify ===");
test_num = 4;
// write
tb_la_addr = 2;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = 8;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
write_reg(2, 8);
$display(" -> wrote 0x0008 to larry_op reg (addr 0x0002)");
// read
tb_la_valid = 1;
tb_la_rw = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
$display(" -> read 0x%h from larry_op reg (addr 0x0002)", la_tb_rdata);
read_reg(2, read_value);
$display(" -> read 0x%h from larry_op reg (addr 0x0002)", read_value);
#(10*`CP);
/* ==== Test 4 End ==== */
@ -220,24 +195,11 @@ module logic_analyzer_tb;
$display("\n=== test 5: write 0x0001 to larry_arg register and verify ===");
test_num = 5;
// write
tb_la_addr = 3;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = 1;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
write_reg(3, 1);
$display(" -> wrote 0x0001 to larry_arg reg (addr 0x0003)");
// read
tb_la_valid = 1;
tb_la_rw = 0;
#`CP
tb_la_valid = 0;
while (!la_tb_valid) #`CP;
$display(" -> read 0x%h from larry_arg reg (addr 0x0003)", la_tb_rdata);
read_reg(3, read_value);
$display(" -> read 0x%h from larry_arg reg (addr 0x0003)", read_value);
#(10*`CP);
/* ==== Test 5 End ==== */
@ -251,7 +213,6 @@ module logic_analyzer_tb;
$display(" -> set larry = 1");
larry = 1;
// read
$display(" -> la core is in state 0x%h", la.fsm.state);
$display(" -> wait a clock cycle");
#`CP
@ -259,7 +220,6 @@ module logic_analyzer_tb;
$display(" -> set larry = 0");
larry = 0;
#(10*`CP);
/* ==== Test 6 End ==== */
@ -269,14 +229,7 @@ module logic_analyzer_tb;
$display("\n=== test 7: set larry = 1, verify core does trigger ===");
test_num = 7;
// write
tb_la_addr = 0;
tb_la_valid = 1;
tb_la_rw = 1;
tb_la_wdata = 1;
#`CP
tb_la_valid = 0;
#`CP
write_reg(0, 1);
$display(" -> wrote 0x0001 to state reg (addr 0x0000)");
#`CP
@ -290,10 +243,81 @@ module logic_analyzer_tb;
#`CP
$display(" -> la core is in state 0x%h", la.fsm.state);
// run until the FILLED state is reached
$display(" -> wait until FILLED state is reached");
while (la.fsm.state != la.fsm.FILLED) begin
{larry, curly, moe, shemp} = {larry, curly, moe, shemp} + 1;
#`CP;
end
$display(" -> read from sample memory:");
read_all_reg();
#(200*`CP);
/* ==== Test 7 End ==== */
/* ==== Test 8 Begin ==== */
$display("\n=== test 8: change trigger to fire on shemp > 3, and verify ===");
test_num = 8;
write_reg(8, 6);
$display(" -> wrote 0x0006 to shemp_op reg (addr 0x0008)");
read_reg(8, read_value);
$display(" -> read 0x%h from shemp_op reg (addr 0x0008)", la_tb_rdata);
write_reg(9, 3);
$display(" -> wrote 0x0003 to shemp_arg reg (addr 0x0009)");
read_reg(9, read_value);
$display(" -> read 0x%h from shemp_arg reg (addr 0x0009)", read_value);
#(10*`CP);
/* ==== Test 8 End ==== */
/* ==== Test 9 Begin ==== */
$display("\n=== test 9: set state machine to IDLE, verify core does not trigger ===");
test_num = 9;
read_reg(0, read_value);
$display(" -> read 0x%h from state reg (addr 0x0000)", read_value);
write_reg(0, 0);
$display(" -> wrote 0x0000 to state reg (addr 0x0000)");
read_reg(0, read_value);
$display(" -> read 0x%h from state reg (addr 0x0000)", read_value);
/* ==== Test 9 End ==== */
/* ==== Test 10 Begin ==== */
$display("\n=== test 10: set shemp = 4, verify core does trigger ===");
test_num = 10;
larry = 0;
curly = 0;
moe = 0;
shemp = 0;
write_reg(0, 1);
$display(" -> wrote 0x0001 to state reg (addr 0x0000)");
shemp = 4;
$display(" -> set shemp = 4");
// run until the FILLED state is reached
$display(" -> wait until FILLED state is reached");
while (la.fsm.state != la.fsm.FILLED) begin
{larry, curly, moe, shemp} = {larry, curly, moe, shemp} + 2;
#`CP;
end
$display(" -> read from sample memory:");
read_all_reg();
#(200*`CP);
/* ==== Test 10 End ==== */
$finish();
end
endmodule