autogenerate logic_analyzer and sample_mem
This commit is contained in:
parent
c5ceccc980
commit
c604614428
|
|
@ -2,7 +2,7 @@
|
|||
`timescale 1ns/1ps
|
||||
|
||||
/*
|
||||
This manta definition was generated on 03 Apr 2023 at 21:11:41 by fischerm
|
||||
This manta definition was generated on 03 Apr 2023 at 22:52:39 by fischerm
|
||||
|
||||
If this breaks or if you've got dank formal verification memes,
|
||||
please contact fischerm [at] mit.edu
|
||||
|
|
@ -55,13 +55,13 @@ module manta (
|
|||
.wdata_o(brx_my_logic_analyzer_wdata),
|
||||
.rw_o(brx_my_logic_analyzer_rw),
|
||||
.valid_o(brx_my_logic_analyzer_valid));
|
||||
|
||||
|
||||
reg [15:0] brx_my_logic_analyzer_addr;
|
||||
reg [15:0] brx_my_logic_analyzer_wdata;
|
||||
reg brx_my_logic_analyzer_rw;
|
||||
reg brx_my_logic_analyzer_valid;
|
||||
|
||||
logic_analyzer #(.BASE_ADDR(0), .SAMPLE_DEPTH(128)) my_logic_analyzer (
|
||||
logic_analyzer my_logic_analyzer (
|
||||
.clk(clk),
|
||||
|
||||
.addr_i(brx_my_logic_analyzer_addr),
|
||||
|
|
@ -161,7 +161,6 @@ endmodule
|
|||
//
|
||||
//
|
||||
|
||||
|
||||
module rx_uart(
|
||||
input wire i_clk,
|
||||
input wire i_uart_rx,
|
||||
|
|
@ -230,8 +229,6 @@ module rx_uart(
|
|||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module bridge_rx(
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -362,17 +359,14 @@ end
|
|||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module logic_analyzer(
|
||||
module logic_analyzer (
|
||||
input wire clk,
|
||||
|
||||
// probes
|
||||
input wire larry,
|
||||
input wire curly,
|
||||
input wire moe,
|
||||
input wire [3:0] shemp,
|
||||
input wire curly,
|
||||
input wire moe,
|
||||
input wire [3:0] shemp,
|
||||
|
||||
// input port
|
||||
input wire [15:0] addr_i,
|
||||
|
|
@ -389,11 +383,11 @@ module logic_analyzer(
|
|||
output reg valid_o
|
||||
);
|
||||
|
||||
parameter BASE_ADDR = 0;
|
||||
parameter SAMPLE_DEPTH = 0;
|
||||
|
||||
// fsm
|
||||
la_fsm #(.BASE_ADDR(BASE_ADDR), .SAMPLE_DEPTH(SAMPLE_DEPTH)) fsm (
|
||||
la_fsm #(
|
||||
.BASE_ADDR(0),
|
||||
.SAMPLE_DEPTH(4096)
|
||||
) fsm (
|
||||
.clk(clk),
|
||||
|
||||
.trig(trig),
|
||||
|
|
@ -421,20 +415,20 @@ module logic_analyzer(
|
|||
reg fsm_trig_blk_valid;
|
||||
|
||||
reg trig;
|
||||
reg [$clog2(SAMPLE_DEPTH):0] fifo_size;
|
||||
reg [$clog2(4096):0] fifo_size;
|
||||
reg fifo_acquire;
|
||||
reg fifo_pop;
|
||||
reg fifo_clear;
|
||||
|
||||
|
||||
// trigger block
|
||||
trigger_block #(.BASE_ADDR(BASE_ADDR + 3)) trig_blk(
|
||||
trigger_block #(.BASE_ADDR(3)) trig_blk (
|
||||
.clk(clk),
|
||||
|
||||
.larry(larry),
|
||||
.curly(curly),
|
||||
.moe(moe),
|
||||
.shemp(shemp),
|
||||
.curly(curly),
|
||||
.moe(moe),
|
||||
.shemp(shemp),
|
||||
|
||||
.trig(trig),
|
||||
|
||||
|
|
@ -457,7 +451,10 @@ module logic_analyzer(
|
|||
reg trig_blk_sample_mem_valid;
|
||||
|
||||
// sample memory
|
||||
sample_mem #(.BASE_ADDR(BASE_ADDR + 11), .SAMPLE_DEPTH(SAMPLE_DEPTH)) sample_mem(
|
||||
sample_mem #(
|
||||
.BASE_ADDR(11),
|
||||
.SAMPLE_DEPTH(4096)
|
||||
) sample_mem (
|
||||
.clk(clk),
|
||||
|
||||
// fifo
|
||||
|
|
@ -468,9 +465,9 @@ module logic_analyzer(
|
|||
|
||||
// probes
|
||||
.larry(larry),
|
||||
.curly(curly),
|
||||
.moe(moe),
|
||||
.shemp(shemp),
|
||||
.curly(curly),
|
||||
.moe(moe),
|
||||
.shemp(shemp),
|
||||
|
||||
// input port
|
||||
.addr_i(trig_blk_sample_mem_addr),
|
||||
|
|
@ -488,8 +485,6 @@ module logic_analyzer(
|
|||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module la_fsm(
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -619,8 +614,6 @@ module la_fsm(
|
|||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module sample_mem(
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -632,9 +625,9 @@ module sample_mem(
|
|||
|
||||
// probes
|
||||
input wire larry,
|
||||
input wire curly,
|
||||
input wire moe,
|
||||
input wire [3:0] shemp,
|
||||
input wire curly,
|
||||
input wire moe,
|
||||
input wire [3:0] shemp,
|
||||
|
||||
// input port
|
||||
input wire [15:0] addr_i,
|
||||
|
|
@ -733,7 +726,6 @@ module sample_mem(
|
|||
end
|
||||
endmodule
|
||||
|
||||
|
||||
// Xilinx True Dual Port RAM, Read First, Dual Clock
|
||||
// This code implements a parameterizable true dual port memory (both ports can read and write).
|
||||
// The behavior of this RAM is when data is written, the prior memory contents at the write
|
||||
|
|
@ -745,19 +737,19 @@ endmodule
|
|||
// Modified from the xilinx_true_dual_port_read_first_2_clock_ram verilog language template.
|
||||
|
||||
module dual_port_bram #(
|
||||
parameter RAM_WIDTH = 0, // Specify RAM data width
|
||||
parameter RAM_DEPTH = 0 // Specify RAM depth (number of entries)
|
||||
parameter RAM_WIDTH = 0,
|
||||
parameter RAM_DEPTH = 0
|
||||
) (
|
||||
input wire [$clog2(RAM_DEPTH-1)-1:0] addra, // Port A address bus, width determined from RAM_DEPTH
|
||||
input wire [$clog2(RAM_DEPTH-1)-1:0] addrb, // Port B address bus, width determined from RAM_DEPTH
|
||||
input wire [RAM_WIDTH-1:0] dina, // Port A RAM input data
|
||||
input wire [RAM_WIDTH-1:0] dinb, // Port B RAM input data
|
||||
input wire clka, // Port A clock
|
||||
input wire clkb, // Port B clock
|
||||
input wire wea, // Port A write enable
|
||||
input wire web, // Port B write enable
|
||||
output wire [RAM_WIDTH-1:0] douta, // Port A RAM output data
|
||||
output wire [RAM_WIDTH-1:0] doutb // Port B RAM output data
|
||||
input wire [$clog2(RAM_DEPTH-1)-1:0] addra,
|
||||
input wire [$clog2(RAM_DEPTH-1)-1:0] addrb,
|
||||
input wire [RAM_WIDTH-1:0] dina,
|
||||
input wire [RAM_WIDTH-1:0] dinb,
|
||||
input wire clka,
|
||||
input wire clkb,
|
||||
input wire wea,
|
||||
input wire web,
|
||||
output wire [RAM_WIDTH-1:0] douta,
|
||||
output wire [RAM_WIDTH-1:0] doutb
|
||||
);
|
||||
|
||||
reg [RAM_WIDTH-1:0] BRAM [RAM_DEPTH-1:0];
|
||||
|
|
@ -774,7 +766,7 @@ module dual_port_bram #(
|
|||
ram_data_b <= BRAM[addrb];
|
||||
end
|
||||
|
||||
// The following is a 2 clock cycle read latency with improve clock-to-out timing
|
||||
// Add a 2 clock cycle read latency to improve clock-to-out timing
|
||||
reg [RAM_WIDTH-1:0] douta_reg = {RAM_WIDTH{1'b0}};
|
||||
reg [RAM_WIDTH-1:0] doutb_reg = {RAM_WIDTH{1'b0}};
|
||||
|
||||
|
|
@ -785,8 +777,6 @@ module dual_port_bram #(
|
|||
assign doutb = doutb_reg;
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
module trigger_block (
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -823,7 +813,7 @@ module trigger_block (
|
|||
reg [3:0] larry_trigger_op = 0;
|
||||
reg larry_trigger_arg = 0;
|
||||
reg larry_trig;
|
||||
|
||||
|
||||
trigger #(.INPUT_WIDTH(1)) larry_trigger (
|
||||
.clk(clk),
|
||||
|
||||
|
|
@ -835,7 +825,7 @@ module trigger_block (
|
|||
reg [3:0] curly_trigger_op = 0;
|
||||
reg curly_trigger_arg = 0;
|
||||
reg curly_trig;
|
||||
|
||||
|
||||
trigger #(.INPUT_WIDTH(1)) curly_trigger (
|
||||
.clk(clk),
|
||||
|
||||
|
|
@ -847,7 +837,7 @@ module trigger_block (
|
|||
reg [3:0] moe_trigger_op = 0;
|
||||
reg moe_trigger_arg = 0;
|
||||
reg moe_trig;
|
||||
|
||||
|
||||
trigger #(.INPUT_WIDTH(1)) moe_trigger (
|
||||
.clk(clk),
|
||||
|
||||
|
|
@ -859,7 +849,7 @@ module trigger_block (
|
|||
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),
|
||||
|
||||
|
|
@ -914,8 +904,6 @@ module trigger_block (
|
|||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module trigger(
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -959,9 +947,6 @@ module trigger(
|
|||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module bridge_tx(
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -1031,9 +1016,6 @@ end
|
|||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
module uart_tx(
|
||||
input wire clk,
|
||||
|
||||
|
|
@ -1105,5 +1087,4 @@ module uart_tx(
|
|||
|
||||
endmodule
|
||||
|
||||
|
||||
`default_nettype wire
|
||||
|
|
@ -437,9 +437,15 @@ class LogicAnalyzerCore:
|
|||
assert len(config["triggers"]) > 0, "Must specify at least one trigger."
|
||||
self.triggers = config["triggers"]
|
||||
|
||||
# need 3 addresses for configuration (state, current_loc, trigger_loc)
|
||||
# and 2 address for each trigger (operation and argument)
|
||||
self.max_addr = self.base_addr + 2 + (2*len(self.probes))
|
||||
|
||||
# compute addresses
|
||||
# - need 3 addresses for configuration (state, current_loc, trigger_loc)
|
||||
# and 2 address for each trigger (operation and argument)
|
||||
|
||||
self.fsm_base_addr = self.base_addr
|
||||
self.trigger_block_base_addr = self.fsm_base_addr + 3
|
||||
self.sample_mem_base_addr = self.trigger_block_base_addr + (2*len(self.probes))
|
||||
self.max_addr = self.sample_mem_base_addr + self.sample_depth
|
||||
|
||||
def hdl_inst(self):
|
||||
ports = []
|
||||
|
|
@ -448,7 +454,7 @@ class LogicAnalyzerCore:
|
|||
ports = "\n\t\t".join(ports)
|
||||
|
||||
hdl = f"""
|
||||
logic_analyzer #(.BASE_ADDR(0), .SAMPLE_DEPTH(128)) {self.name} (
|
||||
logic_analyzer {self.name} (
|
||||
.clk(clk),
|
||||
|
||||
.addr_i(),
|
||||
|
|
@ -481,7 +487,7 @@ class LogicAnalyzerCore:
|
|||
probe_ports.append(f"input wire [{width-1}:0] {name}")
|
||||
|
||||
probe_ports = ",\n\t".join(probe_ports)
|
||||
probe_ports = probe_ports + ","
|
||||
probe_ports = probe_ports + ","
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @PROBE_PORTS", probe_ports)
|
||||
|
||||
# add trigger cores to module definition
|
||||
|
|
@ -490,18 +496,18 @@ class LogicAnalyzerCore:
|
|||
trigger_module_insts = []
|
||||
for name, width in self.probes.items():
|
||||
trigger_module_inst = f"reg [3:0] {name}_trigger_op = 0;\n\t"
|
||||
|
||||
|
||||
if width == 1:
|
||||
trigger_module_inst += f"reg {name}_trigger_arg = 0;\n\t"
|
||||
|
||||
|
||||
else:
|
||||
trigger_module_inst += f"reg [{width-1}:0] {name}_trigger_arg = 0;\n\t"
|
||||
|
||||
|
||||
trigger_module_inst += f"reg {name}_trig;\n\t"
|
||||
trigger_module_inst += f"""
|
||||
trigger_module_inst += f"""
|
||||
trigger #(.INPUT_WIDTH({width})) {name}_trigger (
|
||||
.clk(clk),
|
||||
|
||||
|
||||
.probe({name}),
|
||||
.op({name}_trigger_op),
|
||||
.arg({name}_trigger_arg),
|
||||
|
|
@ -509,9 +515,9 @@ class LogicAnalyzerCore:
|
|||
);
|
||||
"""
|
||||
trigger_module_insts.append(trigger_module_inst)
|
||||
|
||||
|
||||
trigger_module_insts = "".join(trigger_module_insts)
|
||||
trigger_module_insts = trigger_module_insts.rstrip()
|
||||
trigger_module_insts = trigger_module_insts.rstrip()
|
||||
trigger_block_hdl = trigger_block_hdl.replace("// @TRIGGER_MODULE_INSTS", trigger_module_insts)
|
||||
|
||||
# add combined individual triggers
|
||||
|
|
@ -541,18 +547,92 @@ class LogicAnalyzerCore:
|
|||
trigger_block_hdl = trigger_block_hdl.replace("// @MAX_ADDR", str(addr))
|
||||
return trigger_block_hdl
|
||||
|
||||
def generate_sample_mem(self):
|
||||
sample_mem_hdl = pkgutil.get_data(__name__, "sample_mem_template.v").decode()
|
||||
|
||||
# add probe ports to module declaration
|
||||
# - these are the ports that belong to the logic analyzer, but
|
||||
# need to be included in the trigger_block module declaration
|
||||
probe_ports = []
|
||||
for name, width in self.probes.items():
|
||||
if width == 1:
|
||||
probe_ports.append(f"input wire {name}")
|
||||
else:
|
||||
probe_ports.append(f"input wire [{width-1}:0] {name}")
|
||||
|
||||
probe_ports = ",\n\t".join(probe_ports)
|
||||
probe_ports = probe_ports + ","
|
||||
sample_mem_hdl = sample_mem_hdl.replace("/* PROBE_PORTS */", probe_ports)
|
||||
|
||||
|
||||
# concatenate probes to BRAM input
|
||||
total_probe_width = sum([width for name, width in self.probes.items()])
|
||||
|
||||
if total_probe_width > 16:
|
||||
# TODO: implement > 16 bit addressing
|
||||
raise NotImplementedError("ummm i'm getting around to it calm down calm down")
|
||||
|
||||
zero_pad_width = 16 - total_probe_width
|
||||
concat = ", ".join([name for name in self.probes])
|
||||
concat = f"{{{zero_pad_width}'b0, {concat}}}"
|
||||
|
||||
sample_mem_hdl = sample_mem_hdl.replace("/* CONCAT */", concat)
|
||||
|
||||
return sample_mem_hdl
|
||||
|
||||
def generate_logic_analyzer(self):
|
||||
logic_analyzer_hdl = pkgutil.get_data(__name__, "logic_analyzer_template.v").decode()
|
||||
|
||||
# add top level probe ports to module declaration
|
||||
# - these are the ports that belong to the logic analyzer, but
|
||||
# need to be included in the trigger_block module declaration
|
||||
|
||||
tlpp = [] # top level probe ports
|
||||
for name, width in self.probes.items():
|
||||
if width == 1:
|
||||
tlpp.append(f"input wire {name}")
|
||||
else:
|
||||
tlpp.append(f"input wire [{width-1}:0] {name}")
|
||||
|
||||
tlpp = ",\n\t".join(tlpp)
|
||||
tlpp = tlpp + ","
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* TOP_LEVEL_PROBE_PORTS */", tlpp)
|
||||
|
||||
# assign base addresses to the FSM, trigger block, and sample mem
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* FSM_BASE_ADDR */", str(self.fsm_base_addr))
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* TRIGGER_BLOCK_BASE_ADDR */", str(self.trigger_block_base_addr))
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* SAMPLE_MEM_BASE_ADDR */", str(self.sample_mem_base_addr))
|
||||
|
||||
# set sample depth
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* SAMPLE_DEPTH */", str(self.sample_depth))
|
||||
|
||||
# set probe ports for the trigger block and sample mem
|
||||
pp = [] # probe ports
|
||||
pp = [f".{name}({name})" for name in self.probes]
|
||||
pp = ",\n\t\t".join(pp)
|
||||
pp = pp + ","
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* TRIGGER_BLOCK_PROBE_PORTS */", pp)
|
||||
logic_analyzer_hdl = logic_analyzer_hdl.replace("/* SAMPLE_MEM_PROBE_PORTS */", pp)
|
||||
|
||||
return logic_analyzer_hdl
|
||||
|
||||
|
||||
def hdl_def(self):
|
||||
# Return an autogenerated verilog module definition for the core.
|
||||
# load source files
|
||||
logic_analyzer_hdl = pkgutil.get_data(__name__, "logic_analyzer.v").decode()
|
||||
# load source files=
|
||||
la_fsm_hdl = pkgutil.get_data(__name__, "la_fsm.v").decode()
|
||||
sample_mem_hdl = pkgutil.get_data(__name__, "sample_mem.v").decode()
|
||||
dual_port_bram_hdl = pkgutil.get_data(__name__, "dual_port_bram.v").decode()
|
||||
trigger_hdl = pkgutil.get_data(__name__, "trigger.v").decode()
|
||||
|
||||
# generate trigger block
|
||||
trigger_block_hdl = self.generate_trigger_block()
|
||||
|
||||
# generate sample memory
|
||||
sample_mem_hdl = self.generate_sample_mem()
|
||||
|
||||
# generate logic analyzer
|
||||
logic_analyzer_hdl = self.generate_logic_analyzer()
|
||||
|
||||
return logic_analyzer_hdl + la_fsm_hdl + sample_mem_hdl + dual_port_bram_hdl + trigger_block_hdl + trigger_hdl
|
||||
|
||||
def hdl_top_level_ports(self):
|
||||
|
|
@ -568,7 +648,7 @@ class LogicAnalyzerCore:
|
|||
return ports
|
||||
|
||||
def run(self):
|
||||
pass
|
||||
pass
|
||||
|
||||
def part_select(self, data, width):
|
||||
top, bottom = width
|
||||
|
|
@ -946,6 +1026,10 @@ module manta (
|
|||
hdl += module_defs
|
||||
|
||||
# default_nettype and timescale directives only at the beginning and end
|
||||
hdl = hdl.replace("`default_nettype none\n", "")
|
||||
hdl = hdl.replace("`default_nettype wire\n", "")
|
||||
hdl = hdl.replace("`timescale 1ns/1ps\n", "")
|
||||
|
||||
hdl = hdl.replace("`default_nettype none", "")
|
||||
hdl = hdl.replace("`default_nettype wire", "")
|
||||
hdl = hdl.replace("`timescale 1ns/1ps", "")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
`default_nettype none
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module logic_analyzer (
|
||||
input wire clk,
|
||||
|
||||
// probes
|
||||
/* TOP_LEVEL_PROBE_PORTS */
|
||||
|
||||
// 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
|
||||
);
|
||||
|
||||
// fsm
|
||||
la_fsm #(
|
||||
.BASE_ADDR(/* FSM_BASE_ADDR */),
|
||||
.SAMPLE_DEPTH(/* SAMPLE_DEPTH */)
|
||||
) fsm (
|
||||
.clk(clk),
|
||||
|
||||
.trig(trig),
|
||||
.fifo_size(fifo_size),
|
||||
.fifo_acquire(fifo_acquire),
|
||||
.fifo_pop(fifo_pop),
|
||||
.fifo_clear(fifo_clear),
|
||||
|
||||
.addr_i(addr_i),
|
||||
.wdata_i(wdata_i),
|
||||
.rdata_i(rdata_i),
|
||||
.rw_i(rw_i),
|
||||
.valid_i(valid_i),
|
||||
|
||||
.addr_o(fsm_trig_blk_addr),
|
||||
.wdata_o(fsm_trig_blk_wdata),
|
||||
.rdata_o(fsm_trig_blk_rdata),
|
||||
.rw_o(fsm_trig_blk_rw),
|
||||
.valid_o(fsm_trig_blk_valid));
|
||||
|
||||
reg [15:0] fsm_trig_blk_addr;
|
||||
reg [15:0] fsm_trig_blk_wdata;
|
||||
reg [15:0] fsm_trig_blk_rdata;
|
||||
reg fsm_trig_blk_rw;
|
||||
reg fsm_trig_blk_valid;
|
||||
|
||||
reg trig;
|
||||
reg [$clog2(/* SAMPLE_DEPTH */):0] fifo_size;
|
||||
reg fifo_acquire;
|
||||
reg fifo_pop;
|
||||
reg fifo_clear;
|
||||
|
||||
|
||||
// trigger block
|
||||
trigger_block #(.BASE_ADDR(/* TRIGGER_BLOCK_BASE_ADDR */)) trig_blk (
|
||||
.clk(clk),
|
||||
|
||||
/* TRIGGER_BLOCK_PROBE_PORTS */
|
||||
|
||||
.trig(trig),
|
||||
|
||||
.addr_i(fsm_trig_blk_addr),
|
||||
.wdata_i(fsm_trig_blk_wdata),
|
||||
.rdata_i(fsm_trig_blk_rdata),
|
||||
.rw_i(fsm_trig_blk_rw),
|
||||
.valid_i(fsm_trig_blk_valid),
|
||||
|
||||
.addr_o(trig_blk_sample_mem_addr),
|
||||
.wdata_o(trig_blk_sample_mem_wdata),
|
||||
.rdata_o(trig_blk_sample_mem_rdata),
|
||||
.rw_o(trig_blk_sample_mem_rw),
|
||||
.valid_o(trig_blk_sample_mem_valid));
|
||||
|
||||
reg [15:0] trig_blk_sample_mem_addr;
|
||||
reg [15:0] trig_blk_sample_mem_wdata;
|
||||
reg [15:0] trig_blk_sample_mem_rdata;
|
||||
reg trig_blk_sample_mem_rw;
|
||||
reg trig_blk_sample_mem_valid;
|
||||
|
||||
// sample memory
|
||||
sample_mem #(
|
||||
.BASE_ADDR(/* SAMPLE_MEM_BASE_ADDR */),
|
||||
.SAMPLE_DEPTH(/* SAMPLE_DEPTH */)
|
||||
) sample_mem (
|
||||
.clk(clk),
|
||||
|
||||
// fifo
|
||||
.acquire(fifo_acquire),
|
||||
.pop(fifo_pop),
|
||||
.size(fifo_size),
|
||||
.clear(fifo_clear),
|
||||
|
||||
// probes
|
||||
/* SAMPLE_MEM_PROBE_PORTS */
|
||||
|
||||
// input port
|
||||
.addr_i(trig_blk_sample_mem_addr),
|
||||
.wdata_i(trig_blk_sample_mem_wdata),
|
||||
.rdata_i(trig_blk_sample_mem_rdata),
|
||||
.rw_i(trig_blk_sample_mem_rw),
|
||||
.valid_i(trig_blk_sample_mem_valid),
|
||||
|
||||
// output port
|
||||
.addr_o(addr_o),
|
||||
.wdata_o(wdata_o),
|
||||
.rdata_o(rdata_o),
|
||||
.rw_o(rw_o),
|
||||
.valid_o(valid_o));
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
`default_nettype none
|
||||
`timescale 1ns/1ps
|
||||
|
||||
module sample_mem(
|
||||
input wire clk,
|
||||
|
||||
// fifo
|
||||
input wire acquire,
|
||||
input wire pop,
|
||||
output logic [BRAM_ADDR_WIDTH:0] size,
|
||||
input wire clear,
|
||||
|
||||
// probes
|
||||
/* PROBE_PORTS */
|
||||
|
||||
// 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 = 0;
|
||||
localparam BRAM_ADDR_WIDTH = $clog2(SAMPLE_DEPTH);
|
||||
|
||||
// bus controller
|
||||
reg [BRAM_ADDR_WIDTH-1:0] bram_read_addr;
|
||||
reg [15:0] bram_read_data;
|
||||
|
||||
always @(*) begin
|
||||
// if address is valid
|
||||
if ( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + SAMPLE_DEPTH) ) begin
|
||||
|
||||
// figure out proper place to read from
|
||||
// want to read from the read pointer, and then loop back around
|
||||
if(read_pointer + (addr_i - BASE_ADDR) > SAMPLE_DEPTH)
|
||||
bram_read_addr = read_pointer + (addr_i - BASE_ADDR) - SAMPLE_DEPTH;
|
||||
|
||||
else
|
||||
bram_read_addr = read_pointer + (addr_i - BASE_ADDR);
|
||||
end
|
||||
|
||||
else bram_read_addr = 0;
|
||||
end
|
||||
|
||||
|
||||
// pipeline bus to compensate for 2-cycles of delay in BRAM
|
||||
reg [15:0] addr_pip;
|
||||
reg [15:0] wdata_pip;
|
||||
reg [15:0] rdata_pip;
|
||||
reg rw_pip;
|
||||
reg valid_pip;
|
||||
|
||||
always @(posedge clk) begin
|
||||
addr_pip <= addr_i;
|
||||
wdata_pip <= wdata_i;
|
||||
rdata_pip <= rdata_i;
|
||||
rw_pip <= rw_i;
|
||||
valid_pip <= valid_i;
|
||||
|
||||
addr_o <= addr_pip;
|
||||
wdata_o <= wdata_pip;
|
||||
rdata_o <= rdata_pip;
|
||||
rw_o <= rw_pip;
|
||||
valid_o <= valid_pip;
|
||||
|
||||
if( valid_pip && !rw_pip && (addr_pip >= BASE_ADDR) && (addr_pip <= BASE_ADDR + SAMPLE_DEPTH) )
|
||||
rdata_o <= bram_read_data;
|
||||
end
|
||||
|
||||
|
||||
// bram
|
||||
dual_port_bram #(
|
||||
.RAM_WIDTH(16),
|
||||
.RAM_DEPTH(SAMPLE_DEPTH)
|
||||
) bram (
|
||||
// read port (controlled by bus)
|
||||
.clka(clk),
|
||||
.addra(bram_read_addr),
|
||||
.dina(16'b0),
|
||||
.wea(1'b0),
|
||||
.douta(bram_read_data),
|
||||
|
||||
// write port (controlled by FIFO)
|
||||
.clkb(clk),
|
||||
.addrb(write_pointer[BRAM_ADDR_WIDTH-1:0]),
|
||||
.dinb(/* CONCAT */),
|
||||
.web(acquire),
|
||||
.doutb());
|
||||
|
||||
|
||||
// fifo
|
||||
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 (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
|
||||
|
||||
`default_nettype wire
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
from manta import Manta
|
||||
m = Manta('examples/nexys_a7/logic_analyzer/manta.yaml')
|
||||
|
||||
hdl = m.my_logic_analyzer.generate_logic_analyzer()
|
||||
|
||||
with open("test.v", "w") as f:
|
||||
f.write(hdl)
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
`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
|
||||
);
|
||||
|
||||
// fsm
|
||||
la_fsm #(
|
||||
.BASE_ADDR(0),
|
||||
.SAMPLE_DEPTH(4096)
|
||||
|
||||
) fsm (
|
||||
|
||||
.clk(clk),
|
||||
|
||||
.trig(trig),
|
||||
.fifo_size(fifo_size),
|
||||
.fifo_acquire(fifo_acquire),
|
||||
.fifo_pop(fifo_pop),
|
||||
.fifo_clear(fifo_clear),
|
||||
|
||||
.addr_i(addr_i),
|
||||
.wdata_i(wdata_i),
|
||||
.rdata_i(rdata_i),
|
||||
.rw_i(rw_i),
|
||||
.valid_i(valid_i),
|
||||
|
||||
.addr_o(fsm_trig_blk_addr),
|
||||
.wdata_o(fsm_trig_blk_wdata),
|
||||
.rdata_o(fsm_trig_blk_rdata),
|
||||
.rw_o(fsm_trig_blk_rw),
|
||||
.valid_o(fsm_trig_blk_valid));
|
||||
|
||||
reg [15:0] fsm_trig_blk_addr;
|
||||
reg [15:0] fsm_trig_blk_wdata;
|
||||
reg [15:0] fsm_trig_blk_rdata;
|
||||
reg fsm_trig_blk_rw;
|
||||
reg fsm_trig_blk_valid;
|
||||
|
||||
reg trig;
|
||||
reg [$clog2(SAMPLE_DEPTH):0] fifo_size;
|
||||
reg fifo_acquire;
|
||||
reg fifo_pop;
|
||||
reg fifo_clear;
|
||||
|
||||
|
||||
// trigger block
|
||||
trigger_block #(
|
||||
.BASE_ADDR(3)
|
||||
|
||||
) trig_blk (
|
||||
|
||||
.clk(clk),
|
||||
|
||||
.larry(larry),
|
||||
.curly(curly),
|
||||
.moe(moe),
|
||||
.shemp(shemp),
|
||||
|
||||
.trig(trig),
|
||||
|
||||
.addr_i(fsm_trig_blk_addr),
|
||||
.wdata_i(fsm_trig_blk_wdata),
|
||||
.rdata_i(fsm_trig_blk_rdata),
|
||||
.rw_i(fsm_trig_blk_rw),
|
||||
.valid_i(fsm_trig_blk_valid),
|
||||
|
||||
.addr_o(trig_blk_sample_mem_addr),
|
||||
.wdata_o(trig_blk_sample_mem_wdata),
|
||||
.rdata_o(trig_blk_sample_mem_rdata),
|
||||
.rw_o(trig_blk_sample_mem_rw),
|
||||
.valid_o(trig_blk_sample_mem_valid));
|
||||
|
||||
reg [15:0] trig_blk_sample_mem_addr;
|
||||
reg [15:0] trig_blk_sample_mem_wdata;
|
||||
reg [15:0] trig_blk_sample_mem_rdata;
|
||||
reg trig_blk_sample_mem_rw;
|
||||
reg trig_blk_sample_mem_valid;
|
||||
|
||||
// sample memory
|
||||
sample_mem #(
|
||||
.BASE_ADDR(11),
|
||||
.SAMPLE_DEPTH(4096)
|
||||
|
||||
) sample_mem (
|
||||
|
||||
.clk(clk),
|
||||
|
||||
// fifo
|
||||
.acquire(fifo_acquire),
|
||||
.pop(fifo_pop),
|
||||
.size(fifo_size),
|
||||
.clear(fifo_clear),
|
||||
|
||||
// probes
|
||||
.larry(larry),
|
||||
.curly(curly),
|
||||
.moe(moe),
|
||||
.shemp(shemp),
|
||||
|
||||
// input port
|
||||
.addr_i(trig_blk_sample_mem_addr),
|
||||
.wdata_i(trig_blk_sample_mem_wdata),
|
||||
.rdata_i(trig_blk_sample_mem_rdata),
|
||||
.rw_i(trig_blk_sample_mem_rw),
|
||||
.valid_i(trig_blk_sample_mem_valid),
|
||||
|
||||
// output port
|
||||
.addr_o(addr_o),
|
||||
.wdata_o(wdata_o),
|
||||
.rdata_o(rdata_o),
|
||||
.rw_o(rw_o),
|
||||
.valid_o(valid_o));
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
||||
|
|
@ -18,8 +18,7 @@ task read_reg (
|
|||
data = logic_analyzer_tb.la_tb_rdata;
|
||||
|
||||
$display(" -> read 0x%h from addr 0x%h (%s)", data, addr, desc);
|
||||
|
||||
endtask
|
||||
endtask
|
||||
|
||||
task write_reg(
|
||||
input [15:0] addr,
|
||||
|
|
@ -36,7 +35,6 @@ task write_reg(
|
|||
while (!logic_analyzer_tb.la_tb_valid) #`CP;
|
||||
|
||||
$display(" -> wrote 0x%h to addr 0x%h (%s)", data, addr, desc);
|
||||
|
||||
endtask
|
||||
|
||||
task write_and_verify(
|
||||
|
|
|
|||
Loading…
Reference in New Issue