add initialls logic_analyzer core

This commit is contained in:
Fischer Moseley 2023-03-15 15:57:42 -04:00
parent 4540aebf6d
commit fade794333
7 changed files with 537 additions and 33 deletions

View File

@ -3,7 +3,6 @@ on:
push:
branches:
- main
- rearch
permissions:
contents: write
jobs:

View File

@ -8,19 +8,24 @@ lint:
python3 -m black src/manta/__init__.py
python3 -m black src/manta/__main__.py
sim: sim_bit_fifo sim_bridge_rx sim_bridge_tx fifo_tb lut_ram_tb uart_tx_tb
sim: bit_fifo_tb bridge_rx_tb bridge_tx_tb fifo_tb lut_ram_tb uart_tx_tb
sim_bit_fifo:
logic_analyzer_tb:
iverilog -g2012 -o sim.out test/logic_analyzer_tb.sv src/manta/logic_analyzer.v src/manta/fifo.v src/manta/trigger.v src/manta/xilinx_true_dual_port_read_first_2_clock_ram.v
vvp sim.out
rm sim.out
bit_fifo_tb:
iverilog -g2012 -o sim.out test/bit_fifo_tb.sv src/manta/bit_fifo.v
vvp sim.out
rm sim.out
sim_bridge_rx:
bridge_rx_tb:
iverilog -g2012 -o sim.out test/bridge_rx_tb.sv src/manta/bridge_rx.v
vvp sim.out
rm sim.out
sim_bridge_tx:
bridge_tx_tb:
iverilog -g2012 -o sim.out test/bridge_tx_tb.sv src/manta/bridge_tx.v src/manta/uart_tx.v
vvp sim.out
rm sim.out

View File

@ -3,14 +3,14 @@
module fifo (
input wire clk,
input wire rst,
input wire bram_rst,
input wire [WIDTH - 1:0] data_in,
input wire input_ready,
input wire [WIDTH - 1:0] in,
input wire in_valid,
input wire request_output,
output reg [WIDTH - 1:0] data_out,
output reg output_valid,
output reg [WIDTH - 1:0] out,
input wire out_req,
output reg out_valid,
output reg [AW:0] size,
output reg empty,
@ -28,28 +28,24 @@ module fifo (
assign empty_int = (write_pointer[AW] == read_pointer[AW]);
reg full_or_empty;
assign full_or_empty = (write_pointer[AW-1:0] == read_pointer[AW-1:0]);
assign full_or_empty = (write_pointer[AW-1:0] == read_pointer[AW-1:0]);
assign full = full_or_empty & !empty_int;
assign empty = full_or_empty & empty_int;
assign size = write_pointer - read_pointer;
reg output_valid_pip_0;
reg output_valid_pip_1;
reg out_valid_pip_0;
reg out_valid_pip_1;
always @(posedge clk) begin
if (input_ready && ~full)
if (in_valid && ~full)
write_pointer <= write_pointer + 1'd1;
if (request_output && ~empty)
if (out_req && ~empty) begin
read_pointer <= read_pointer + 1'd1;
output_valid_pip_0 <= request_output;
output_valid_pip_1 <= output_valid_pip_0;
output_valid <= output_valid_pip_1;
if (rst) begin
read_pointer <= 0;
write_pointer <= 0;
out_valid_pip_0 <= out_req;
out_valid_pip_1 <= out_valid_pip_0;
out_valid <= out_valid_pip_1;
end
end
@ -62,23 +58,23 @@ module fifo (
// write port
.clka(clk),
.rsta(rst),
.ena(1),
.rsta(bram_rst),
.ena(1'b1),
.addra(write_pointer),
.dina(data_in),
.wea(input_ready),
.regcea(1),
.dina(in),
.wea(in_valid),
.regcea(1'b1),
.douta(),
// read port
.clkb(clk),
.rstb(rst),
.enb(1),
.rstb(bram_rst),
.enb(1'b1),
.addrb(read_pointer),
.dinb(),
.web(0),
.regceb(1),
.doutb(data_out));
.web(1'b0),
.regceb(1'b1),
.doutb(out));
endmodule
`default_nettype wire

226
src/manta/logic_analyzer.v Normal file
View File

@ -0,0 +1,226 @@
`default_nettype none
`timescale 1ns/1ps
module logic_analyzer(
input wire clk,
// probes
input wire larry,
input wire curly,
input wire moe,
input wire [3:0] shemp,
// input port
input wire [15:0] addr_i,
input wire [15:0] wdata_i,
input wire [15:0] rdata_i,
input wire rw_i,
input wire valid_i,
// output port
output reg [15:0] addr_o,
output reg [15:0] wdata_o,
output reg [15:0] rdata_o,
output reg rw_o,
output reg valid_o
);
parameter BASE_ADDR = 0;
parameter SAMPLE_DEPTH = 4096;
// trigger configuration registers
// - each probe gets an operation and a compare register
// - at the end we AND them all together. along with any custom probes the user specs
reg [3:0] larry_trigger_op;
reg larry_trigger_arg;
reg larry_trig;
trigger #(.INPUT_WIDTH(1)) larry_trigger(
.clk(clk),
.probe(larry),
.op(larry_trigger_op),
.arg(larry_trigger_arg),
.trig(larry_trig));
reg [3:0] curly_trigger_op;
reg curly_trigger_arg;
reg curly_trig;
trigger #(.INPUT_WIDTH(1)) curly_trigger(
.clk(clk),
.probe(curly),
.op(curly_trigger_op),
.arg(curly_trigger_arg),
.trig(curly_trig));
reg [3:0] moe_trigger_op;
reg moe_trigger_arg;
reg moe_trig;
trigger #(.INPUT_WIDTH(1)) moe_trigger(
.clk(clk),
.probe(moe),
.op(moe_trigger_op),
.arg(moe_trigger_arg),
.trig(moe_trig));
reg [3:0] shemp_trigger_op;
reg [3:0] shemp_trigger_arg;
reg shemp_trig;
trigger #(.INPUT_WIDTH(4)) shemp_trigger(
.clk(clk),
.probe(shemp),
.op(shemp_trigger_op),
.arg(shemp_trigger_arg),
.trig(shemp_trig));
reg triggered;
assign triggered = larry_trig || curly_trig || moe_trig || shemp_trig;
reg [6:0] concatenated;
assign concatenated = {larry, curly, moe, shemp};
// word-wise fifo
fifo #(.WIDTH(FIFO_WIDTH), .DEPTH(SAMPLE_DEPTH)) wfifo(
.clk(clk),
.bram_rst(1'b0),
.in(concatenated),
.in_valid(wfifo_in_valid),
.out(wfifo_out),
.out_req(wfifo_out_req),
.out_valid(wfifo_out_valid),
.size(wfifo_size),
.empty(),
.full());
reg wfifo_in_valid;
localparam FIFO_WIDTH = 7;
reg [FIFO_WIDTH-1:0] wfifo_out;
reg wfifo_out_req;
reg wfifo_out_valid;
reg [$clog2(SAMPLE_DEPTH):0] wfifo_size;
// state machine
localparam IDLE = 0;
localparam START = 1;
localparam MOVE_TO_POSITION = 2;
localparam IN_POSITION = 3;
localparam FILLING_BUFFER = 4;
localparam FILLED = 5;
reg [3:0] state;
initial state = IDLE;
reg signed [15:0] trigger_loc;
initial trigger_loc = 0;
reg signed [15:0] present_loc;
initial present_loc = 0;
always @(posedge clk) begin
if(state == IDLE) begin
present_loc <= (trigger_loc < 0) ? trigger_loc : 0;
end
else if(state == MOVE_TO_POSITION) begin
// if trigger location is negative or zero,
// then we're already in position
if(trigger_loc <= 0) state <= IN_POSITION;
// otherwise we'll need to wait a little,
// but we'll need to buffer along the way
else begin
present_loc <= present_loc + 1;
// add code to add samples to word FIFO
wfifo_in_valid <= 1;
if (present_loc == trigger_loc) state <= IN_POSITION;
end
end
else if(state == IN_POSITION) begin
// pop stuff out of the word FIFO in addition to pulling it in
wfifo_in_valid <= 1;
wfifo_out_req <= 1;
if(triggered) state <= FILLING_BUFFER;
end
else if(state == FILLING_BUFFER) begin
if(wfifo_size == SAMPLE_DEPTH) state <= FILLED;
end
else if(state == FILLED) begin
// don't automatically go back to IDLE, the host will move
// the state to MOVE_TO_POSITION
present_loc <= (trigger_loc < 0) ? trigger_loc : 0;
end
end
// memory servicing
// - TODO: add support for comparision values > 16 bits,
// we'll have to concat them somwehere up here
always @(posedge clk) begin
addr_o <= addr_i;
wdata_o <= wdata_i;
rdata_o <= rdata_i;
rw_o <= rw_i;
valid_o <= valid_i;
// operations to configuration registers
if( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + 9) ) begin
// reads
if(valid_i && !rw_i) begin
case (addr_i)
BASE_ADDR + 0: rdata_o <= state;
BASE_ADDR + 1: rdata_o <= trigger_loc;
BASE_ADDR + 2: rdata_o <= larry_trigger_op;
BASE_ADDR + 3: rdata_o <= larry_trigger_arg;
BASE_ADDR + 4: rdata_o <= curly_trigger_op;
BASE_ADDR + 5: rdata_o <= curly_trigger_arg;
BASE_ADDR + 6: rdata_o <= moe_trigger_op;
BASE_ADDR + 7: rdata_o <= moe_trigger_arg;
BASE_ADDR + 8: rdata_o <= shemp_trigger_op;
BASE_ADDR + 9: rdata_o <= shemp_trigger_arg;
default: rdata_o <= rdata_i;
endcase
end
// writes
else if(valid_i && rw_i) begin
case (addr_i)
BASE_ADDR + 0: state <= wdata_i;
BASE_ADDR + 1: trigger_loc <= wdata_i;
BASE_ADDR + 2: larry_trigger_op <= wdata_i;
BASE_ADDR + 3: larry_trigger_arg <= wdata_i;
BASE_ADDR + 4: curly_trigger_op <= wdata_i;
BASE_ADDR + 5: curly_trigger_arg <= wdata_i;
BASE_ADDR + 6: moe_trigger_op <= wdata_i;
BASE_ADDR + 7: moe_trigger_arg <= wdata_i;
BASE_ADDR + 8: shemp_trigger_op <= wdata_i;
BASE_ADDR + 9: shemp_trigger_arg <= wdata_i;
default: wdata_o <= wdata_i;
endcase
end
end
// operations to BRAM
else if( (addr_i >= BASE_ADDR + 10) && (addr_i <= BASE_ADDR + 10 + SAMPLE_DEPTH) ) begin
end
end
endmodule
`default_nettype wire

47
src/manta/trigger.v Normal file
View File

@ -0,0 +1,47 @@
`default_nettype none
`timescale 1ns/1ps
module trigger(
input wire clk,
input wire [INPUT_WIDTH-1:0] probe,
input wire [3:0] op,
input wire [INPUT_WIDTH-1:0] arg,
output reg trig
);
parameter INPUT_WIDTH = 0;
localparam DISABLE = 0;
localparam RISING = 1;
localparam FALLING = 2;
localparam CHANGING = 3;
localparam GT = 4;
localparam LT = 5;
localparam GEQ = 6;
localparam LEQ = 7;
localparam EQ = 8;
localparam NEQ = 9;
reg [INPUT_WIDTH-1:0] probe_prev;
initial probe_prev = probe;
always @(posedge clk) probe_prev <= probe;
always @(*) begin
case (op)
RISING : trig = (probe > probe_prev);
FALLING : trig = (probe < probe_prev);
CHANGING : trig = (probe != probe_prev);
GT: trig = (probe > arg);
LT: trig = (probe < arg);
GEQ: trig = (probe >= arg);
LEQ: trig = (probe <= arg);
EQ: trig = (probe == arg);
NEQ: trig = (probe != arg);
default: trig = 0;
endcase
end
endmodule
`default_nettype wire

231
test/logic_analyzer_tb.sv Normal file
View File

@ -0,0 +1,231 @@
`default_nettype none
`define CP 10
`define HCP 5
module logic_analyzer_tb;
// boilerplate
logic clk;
integer test_num;
// signal generator
logic larry;
logic curly;
logic moe;
logic [3:0] shemp;
// tb -> la bus
logic [15:0] tb_la_addr;
logic [15:0] tb_la_wdata;
logic [15:0] tb_la_rdata;
logic tb_la_rw;
logic tb_la_valid;
// la -> tb bus
logic [15:0] la_tb_addr;
logic [15:0] la_tb_wdata;
logic [15:0] la_tb_rdata;
logic la_tb_rw;
logic la_tb_valid;
logic_analyzer la(
.clk(clk),
// probes
.larry(larry),
.curly(curly),
.moe(moe),
.shemp(shemp),
// input port
.addr_i(tb_la_addr),
.wdata_i(tb_la_wdata),
.rdata_i(tb_la_rdata),
.rw_i(tb_la_rw),
.valid_i(tb_la_valid),
// output port
.addr_o(la_tb_addr),
.wdata_o(la_tb_wdata),
.rdata_o(la_tb_rdata),
.rw_o(la_tb_rw),
.valid_o(la_tb_valid));
always begin
#`HCP
clk = !clk;
end
initial begin
$dumpfile("logic_analyzer_tb.vcd");
$dumpvars(0, logic_analyzer_tb);
// setup and reset
clk = 0;
test_num = 0;
tb_la_addr = 0;
tb_la_rdata = 0;
tb_la_wdata = 0;
tb_la_rw = 0;
tb_la_valid = 0;
larry = 0;
curly = 0;
moe = 0;
shemp = 0;
#`HCP
#(10*`CP);
/* ==== Test 1 Begin ==== */
$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);
#(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;
#`CP
$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);
#(10*`CP);
/* ==== Test 2 End ==== */
/* ==== Test 3 Begin ==== */
$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;
#`CP
$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));
#(10*`CP);
/* ==== Test 3 End ==== */
/* ==== Test 4 Begin ==== */
$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;
#`CP
$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);
#(10*`CP);
/* ==== Test 4 End ==== */
/* ==== Test 5 Begin ==== */
$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;
#`CP
$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);
#(10*`CP);
/* ==== Test 5 End ==== */
/* ==== Test 6 Begin ==== */
$display("\n=== test 6: set larry = 1, verify core does not trigger ===");
test_num = 6;
larry = 1;
$display(" -> set larry = 1");
// read
$display(" -> la core is in state 0x%h", la.state);
#`CP
$display(" -> la core is in state 0x%h", la.state);
#(10*`CP);
/* ==== Test 6 End ==== */
$finish();
end
endmodule
`default_nettype wire