add boilerplate for new modules - just gotta rewrite the fsm
This commit is contained in:
parent
4d2c3d08e6
commit
bdca8e01e7
5
Makefile
5
Makefile
|
|
@ -32,10 +32,7 @@ auto_gen:
|
||||||
functional_sim: io_core_tb logic_analyzer_tb bit_fifo_tb bridge_rx_tb bridge_tx_tb lut_ram_tb
|
functional_sim: io_core_tb logic_analyzer_tb bit_fifo_tb bridge_rx_tb bridge_tx_tb lut_ram_tb
|
||||||
|
|
||||||
block_memory_tb:
|
block_memory_tb:
|
||||||
cd test/functional_sim/block_memory_tb/ && python3 foo.py
|
iverilog -g2012 -o sim.out -y src/manta test/functional_sim/block_memory_tb.sv
|
||||||
iverilog -g2012 -o sim.out -y src/manta \
|
|
||||||
test/functional_sim/block_memory_tb/block_memory_tb.sv \
|
|
||||||
test/functional_sim/block_memory_tb/block_memory.v
|
|
||||||
vvp sim.out
|
vvp sim.out
|
||||||
rm sim.out
|
rm sim.out
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
`default_nettype none
|
|
||||||
`timescale 1ns/1ps
|
|
||||||
|
|
||||||
module la_fsm(
|
|
||||||
input wire clk,
|
|
||||||
|
|
||||||
input wire trig,
|
|
||||||
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,
|
|
||||||
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;
|
|
||||||
|
|
||||||
// state machine
|
|
||||||
localparam IDLE = 0;
|
|
||||||
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;
|
|
||||||
reg signed [15:0] present_loc;
|
|
||||||
|
|
||||||
initial state = IDLE;
|
|
||||||
initial trigger_loc = 0;
|
|
||||||
initial present_loc = 0;
|
|
||||||
|
|
||||||
// perform register operations
|
|
||||||
always @(posedge clk) begin
|
|
||||||
addr_o <= addr_i;
|
|
||||||
wdata_o <= wdata_i;
|
|
||||||
rdata_o <= rdata_i;
|
|
||||||
rw_o <= rw_i;
|
|
||||||
valid_o <= valid_i;
|
|
||||||
|
|
||||||
// check if address is valid
|
|
||||||
if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + 2)) begin
|
|
||||||
|
|
||||||
if(!rw_i) begin // reads
|
|
||||||
case (addr_i)
|
|
||||||
BASE_ADDR + 0: rdata_o <= state;
|
|
||||||
BASE_ADDR + 1: rdata_o <= trigger_loc;
|
|
||||||
BASE_ADDR + 2: rdata_o <= present_loc;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
else begin // writes
|
|
||||||
case (addr_i)
|
|
||||||
BASE_ADDR + 0: state <= wdata_i;
|
|
||||||
BASE_ADDR + 1: trigger_loc <= wdata_i;
|
|
||||||
//BASE_ADDR + 2: present_loc <= wdata_i;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// end
|
|
||||||
|
|
||||||
// run state machine
|
|
||||||
// always @(posedge clk) begin
|
|
||||||
if(state == IDLE) begin
|
|
||||||
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;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
fifo_acquire <= 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
|
|
||||||
fifo_acquire <= 1;
|
|
||||||
fifo_pop <= 1;
|
|
||||||
|
|
||||||
if(trig) state <= FILLING_BUFFER;
|
|
||||||
end
|
|
||||||
|
|
||||||
else if(state == FILLING_BUFFER) begin
|
|
||||||
fifo_acquire <= 1;
|
|
||||||
fifo_pop <= 0;
|
|
||||||
if(fifo_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
|
|
||||||
|
|
||||||
|
|
||||||
// return to IDLE state if somehow we get to a state that doesn't exist
|
|
||||||
else begin
|
|
||||||
state <= IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
`default_nettype wire
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
`default_nettype none
|
||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module logic_analyzer_controller (
|
||||||
|
input wire clk,
|
||||||
|
|
||||||
|
// from register file
|
||||||
|
output reg [3:0] state,
|
||||||
|
input wire signed [15:0] trigger_loc,
|
||||||
|
output reg signed [15:0] current_loc,
|
||||||
|
input wire request_start,
|
||||||
|
input wire request_stop,
|
||||||
|
output reg read_pointer,
|
||||||
|
|
||||||
|
// from trigger block
|
||||||
|
input wire trig,
|
||||||
|
|
||||||
|
// block memory user port
|
||||||
|
output [ADDR_WIDTH-1:0] bram_addr,
|
||||||
|
output bram_we
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter DEPTH = 0;
|
||||||
|
localparam ADDR_WIDTH = $clog2(DEPTH);
|
||||||
|
|
||||||
|
// fsm
|
||||||
|
localparam IDLE = 0;
|
||||||
|
localparam START_CAPTURE = 1;
|
||||||
|
localparam MOVE_TO_POSITION = 2;
|
||||||
|
localparam IN_POSITION = 3;
|
||||||
|
localparam FILLING_BUFFER = 4;
|
||||||
|
localparam FILLED = 5;
|
||||||
|
|
||||||
|
initial state = IDLE;
|
||||||
|
initial current_loc = 0;
|
||||||
|
initial read_pointer = 0;
|
||||||
|
initial write_pointer = 0;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if(state == IDLE) begin
|
||||||
|
current_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;
|
||||||
|
|
||||||
|
// otherwise we'll need to wait a little,
|
||||||
|
// but we'll need to buffer along the way
|
||||||
|
else begin
|
||||||
|
current_loc <= current_loc + 1;
|
||||||
|
// add code to add samples to word FIFO
|
||||||
|
fifo_acquire <= 1;
|
||||||
|
if (current_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
|
||||||
|
fifo_acquire <= 1;
|
||||||
|
fifo_pop <= 1;
|
||||||
|
|
||||||
|
if(trig) state <= FILLING_BUFFER;
|
||||||
|
end
|
||||||
|
|
||||||
|
else if(state == FILLING_BUFFER) begin
|
||||||
|
fifo_acquire <= 1;
|
||||||
|
fifo_pop <= 0;
|
||||||
|
if(fifo_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
|
||||||
|
|
||||||
|
current_loc <= (trigger_loc < 0) ? trigger_loc : 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// return to IDLE state if somehow we get to a state that doesn't exist
|
||||||
|
else begin
|
||||||
|
state <= IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// fifo
|
||||||
|
reg acquire;
|
||||||
|
reg pop;
|
||||||
|
reg [ADDR_WIDTH:0] size,
|
||||||
|
reg clear,
|
||||||
|
|
||||||
|
reg [ADDR_WIDTH:0] write_pointer = 0;
|
||||||
|
reg [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 < DEPTH) write_pointer <= write_pointer + 1'd1;
|
||||||
|
if (pop && size > 0) read_pointer <= read_pointer + 1'd1;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`default_nettype wire
|
||||||
|
|
@ -22,18 +22,48 @@ module logic_analyzer (
|
||||||
output reg valid_o
|
output reg valid_o
|
||||||
);
|
);
|
||||||
|
|
||||||
// fsm
|
parameter SAMPLE_DEPTH = 0;
|
||||||
la_fsm #(
|
localparam ADDR_WIDTH = $clog2(SAMPLE_DEPTH);
|
||||||
.BASE_ADDR(/* FSM_BASE_ADDR */),
|
|
||||||
.SAMPLE_DEPTH(/* SAMPLE_DEPTH */)
|
reg [3:0] state;
|
||||||
) fsm (
|
reg signed [15:0] trigger_loc;
|
||||||
|
reg signed [15:0] current_loc;
|
||||||
|
reg request_start;
|
||||||
|
reg request_stop;
|
||||||
|
reg [ADDR_WIDTH-1:0] read_pointer;
|
||||||
|
|
||||||
|
reg trig;
|
||||||
|
|
||||||
|
reg [ADDR_WIDTH-1:0] bram_addr;
|
||||||
|
reg bram_we;
|
||||||
|
|
||||||
|
localparam TOTAL_PROBE_WIDTH = 0;
|
||||||
|
reg [TOTAL_PROBE_WIDTH-1:0] probes_concat;
|
||||||
|
assign probes_concat = /* PROBES_CONCAT */;
|
||||||
|
|
||||||
|
logic_analyzer_controller la_controller (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
|
|
||||||
|
// from register file
|
||||||
|
.state(state),
|
||||||
|
.trigger_loc(trigger_loc),
|
||||||
|
.current_loc(current_loc),
|
||||||
|
.request_start(request_start),
|
||||||
|
.request_stop(request_stop),
|
||||||
|
.read_pointer(read_pointer),
|
||||||
|
|
||||||
|
// from trigger block
|
||||||
.trig(trig),
|
.trig(trig),
|
||||||
.fifo_size(fifo_size),
|
|
||||||
.fifo_acquire(fifo_acquire),
|
// from block memory user port
|
||||||
.fifo_pop(fifo_pop),
|
.bram_addr(bram_addr),
|
||||||
.fifo_clear(fifo_clear),
|
.bram_we(bram_we)
|
||||||
|
);
|
||||||
|
|
||||||
|
logic_analyzer_fsm_registers #(
|
||||||
|
.BASE_ADDR(/* FSM_BASE_ADDR */)
|
||||||
|
) fsm_registers (
|
||||||
|
.clk(clk),
|
||||||
|
|
||||||
.addr_i(addr_i),
|
.addr_i(addr_i),
|
||||||
.wdata_i(wdata_i),
|
.wdata_i(wdata_i),
|
||||||
|
|
@ -41,24 +71,26 @@ module logic_analyzer (
|
||||||
.rw_i(rw_i),
|
.rw_i(rw_i),
|
||||||
.valid_i(valid_i),
|
.valid_i(valid_i),
|
||||||
|
|
||||||
.addr_o(fsm_trig_blk_addr),
|
.addr_o(fsm_reg_trig_blk_addr),
|
||||||
.wdata_o(fsm_trig_blk_wdata),
|
.wdata_o(fsm_reg_trig_blk_wdata),
|
||||||
.rdata_o(fsm_trig_blk_rdata),
|
.rdata_o(fsm_reg_trig_blk_rdata),
|
||||||
.rw_o(fsm_trig_blk_rw),
|
.rw_o(fsm_reg_trig_blk_rw),
|
||||||
.valid_o(fsm_trig_blk_valid));
|
.valid_o(fsm_reg_trig_blk_valid),
|
||||||
|
|
||||||
reg [15:0] fsm_trig_blk_addr;
|
.state(state),
|
||||||
reg [15:0] fsm_trig_blk_wdata;
|
.trigger_loc(trigger_loc),
|
||||||
reg [15:0] fsm_trig_blk_rdata;
|
.current_loc(current_loc),
|
||||||
reg fsm_trig_blk_rw;
|
.request_start(request_start),
|
||||||
reg fsm_trig_blk_valid;
|
.request_stop(request_stop),
|
||||||
|
.read_pointer(read_pointer));
|
||||||
|
|
||||||
|
reg [15:0] fsm_reg_trig_blk_addr;
|
||||||
|
reg [15:0] fsm_reg_trig_blk_wdata;
|
||||||
|
reg [15:0] fsm_reg_trig_blk_rdata;
|
||||||
|
reg fsm_reg_trig_blk_rw;
|
||||||
|
reg fsm_reg_trig_blk_valid;
|
||||||
|
|
||||||
reg trig;
|
reg trig;
|
||||||
reg [$clog2(/* SAMPLE_DEPTH */):0] fifo_size;
|
|
||||||
reg fifo_acquire;
|
|
||||||
reg fifo_pop;
|
|
||||||
reg fifo_clear;
|
|
||||||
|
|
||||||
|
|
||||||
// trigger block
|
// trigger block
|
||||||
trigger_block #(.BASE_ADDR(/* TRIGGER_BLOCK_BASE_ADDR */)) trig_blk (
|
trigger_block #(.BASE_ADDR(/* TRIGGER_BLOCK_BASE_ADDR */)) trig_blk (
|
||||||
|
|
@ -68,53 +100,52 @@ module logic_analyzer (
|
||||||
|
|
||||||
.trig(trig),
|
.trig(trig),
|
||||||
|
|
||||||
.addr_i(fsm_trig_blk_addr),
|
.addr_i(fsm_reg_trig_blk_addr),
|
||||||
.wdata_i(fsm_trig_blk_wdata),
|
.wdata_i(fsm_reg_trig_blk_wdata),
|
||||||
.rdata_i(fsm_trig_blk_rdata),
|
.rdata_i(fsm_reg_trig_blk_rdata),
|
||||||
.rw_i(fsm_trig_blk_rw),
|
.rw_i(fsm_reg_trig_blk_rw),
|
||||||
.valid_i(fsm_trig_blk_valid),
|
.valid_i(fsm_reg_trig_blk_valid),
|
||||||
|
|
||||||
.addr_o(trig_blk_sample_mem_addr),
|
.addr_o(trig_blk_block_mem_addr),
|
||||||
.wdata_o(trig_blk_sample_mem_wdata),
|
.wdata_o(trig_blk_block_mem_wdata),
|
||||||
.rdata_o(trig_blk_sample_mem_rdata),
|
.rdata_o(trig_blk_block_mem_rdata),
|
||||||
.rw_o(trig_blk_sample_mem_rw),
|
.rw_o(trig_blk_block_mem_rw),
|
||||||
.valid_o(trig_blk_sample_mem_valid));
|
.valid_o(trig_blk_block_mem_valid));
|
||||||
|
|
||||||
reg [15:0] trig_blk_sample_mem_addr;
|
reg [15:0] trig_blk_block_mem_addr;
|
||||||
reg [15:0] trig_blk_sample_mem_wdata;
|
reg [15:0] trig_blk_block_mem_wdata;
|
||||||
reg [15:0] trig_blk_sample_mem_rdata;
|
reg [15:0] trig_blk_block_mem_rdata;
|
||||||
reg trig_blk_sample_mem_rw;
|
reg trig_blk_block_mem_rw;
|
||||||
reg trig_blk_sample_mem_valid;
|
reg trig_blk_block_mem_valid;
|
||||||
|
|
||||||
// sample memory
|
// sample memory
|
||||||
sample_mem #(
|
block_memory #(
|
||||||
.BASE_ADDR(/* SAMPLE_MEM_BASE_ADDR */),
|
.BASE_ADDR(/* SAMPLE_MEM_BASE_ADDR */),
|
||||||
.SAMPLE_DEPTH(/* SAMPLE_DEPTH */)
|
.WIDTH(),
|
||||||
) sample_mem (
|
.DEPTH(/* SAMPLE_DEPTH */)
|
||||||
|
) block_mem (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
|
|
||||||
// fifo
|
|
||||||
.acquire(fifo_acquire),
|
|
||||||
.pop(fifo_pop),
|
|
||||||
.size(fifo_size),
|
|
||||||
.clear(fifo_clear),
|
|
||||||
|
|
||||||
// probes
|
|
||||||
/* SAMPLE_MEM_PROBE_PORTS */
|
|
||||||
|
|
||||||
// input port
|
// input port
|
||||||
.addr_i(trig_blk_sample_mem_addr),
|
.addr_i(trig_blk_block_mem_addr),
|
||||||
.wdata_i(trig_blk_sample_mem_wdata),
|
.wdata_i(trig_blk_block_mem_wdata),
|
||||||
.rdata_i(trig_blk_sample_mem_rdata),
|
.rdata_i(trig_blk_block_mem_rdata),
|
||||||
.rw_i(trig_blk_sample_mem_rw),
|
.rw_i(trig_blk_block_mem_rw),
|
||||||
.valid_i(trig_blk_sample_mem_valid),
|
.valid_i(trig_blk_block_mem_valid),
|
||||||
|
|
||||||
// output port
|
// output port
|
||||||
.addr_o(addr_o),
|
.addr_o(addr_o),
|
||||||
.wdata_o(wdata_o),
|
.wdata_o(wdata_o),
|
||||||
.rdata_o(rdata_o),
|
.rdata_o(rdata_o),
|
||||||
.rw_o(rw_o),
|
.rw_o(rw_o),
|
||||||
.valid_o(valid_o));
|
.valid_o(valid_o),
|
||||||
|
|
||||||
|
// BRAM itself
|
||||||
|
.user_clk(clk),
|
||||||
|
.user_addr(bram_addr),
|
||||||
|
.user_din(probes_concat),
|
||||||
|
.user_dout(),
|
||||||
|
.user_we(bram_we));
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
`default_nettype wire
|
`default_nettype wire
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
`default_nettype none
|
||||||
|
`timescale 1ns/1ps
|
||||||
|
|
||||||
|
module logic_analyzer_fsm_registers(
|
||||||
|
input wire clk,
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
|
||||||
|
// registers
|
||||||
|
input wire [3:0] state,
|
||||||
|
output reg signed [15:0] trigger_loc,
|
||||||
|
input wire signed [15:0] current_loc,
|
||||||
|
output reg request_start,
|
||||||
|
output reg request_stop,
|
||||||
|
input wire [15:0] read_pointer
|
||||||
|
);
|
||||||
|
|
||||||
|
parameter BASE_ADDR = 0;
|
||||||
|
localparam MAX_ADDR = BASE_ADDR + 5;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
addr_o <= addr_i;
|
||||||
|
wdata_o <= wdata_i;
|
||||||
|
rdata_o <= rdata_i;
|
||||||
|
rw_o <= rw_i;
|
||||||
|
valid_o <= valid_i;
|
||||||
|
|
||||||
|
// check if address is valid
|
||||||
|
if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= MAX_ADDR)) begin
|
||||||
|
|
||||||
|
// reads
|
||||||
|
if(!rw_i) begin
|
||||||
|
case (addr_i)
|
||||||
|
BASE_ADDR + 0: rdata_o <= state;
|
||||||
|
BASE_ADDR + 1: rdata_o <= trigger_loc;
|
||||||
|
BASE_ADDR + 2: rdata_o <= current_loc;
|
||||||
|
BASE_ADDR + 3: rdata_o <= request_start;
|
||||||
|
BASE_ADDR + 4: rdata_o <= request_stop;
|
||||||
|
BASE_ADDR + 5: rdata_o <= read_pointer;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// writes
|
||||||
|
else begin
|
||||||
|
case (addr_i)
|
||||||
|
BASE_ADDR + 1: trigger_loc <= wdata_i;
|
||||||
|
BASE_ADDR + 3: request_start <= wdata_i;
|
||||||
|
BASE_ADDR + 4: request_stop <= wdata_i;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
`default_nettype wire
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
`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
|
|
||||||
|
|
@ -3,10 +3,13 @@
|
||||||
`define CP 10
|
`define CP 10
|
||||||
`define HCP 5
|
`define HCP 5
|
||||||
|
|
||||||
task read_reg (
|
`define BRAM_DEPTH 256
|
||||||
|
`define BRAM_WIDTH 33
|
||||||
|
`define ADDR_WIDTH $clog2(`BRAM_DEPTH)
|
||||||
|
|
||||||
|
task read_reg_bus_side (
|
||||||
input [15:0] addr,
|
input [15:0] addr,
|
||||||
output [15:0] data,
|
output [15:0] data
|
||||||
input string desc
|
|
||||||
);
|
);
|
||||||
|
|
||||||
block_memory_tb.tb_bc_addr = addr;
|
block_memory_tb.tb_bc_addr = addr;
|
||||||
|
|
@ -18,13 +21,12 @@ task read_reg (
|
||||||
while (!block_memory_tb.bc_tb_valid) #`CP;
|
while (!block_memory_tb.bc_tb_valid) #`CP;
|
||||||
data = block_memory_tb.bc_tb_rdata;
|
data = block_memory_tb.bc_tb_rdata;
|
||||||
|
|
||||||
$display(" -> read 0x%h from addr 0x%h (%s)", data, addr, desc);
|
$display(" -> bus read 0x%h from addr 0x%h", data, addr);
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task write_reg(
|
task write_reg_bus_side(
|
||||||
input [15:0] addr,
|
input [15:0] addr,
|
||||||
input [15:0] data,
|
input [15:0] data
|
||||||
input string desc
|
|
||||||
);
|
);
|
||||||
|
|
||||||
block_memory_tb.tb_bc_addr = addr;
|
block_memory_tb.tb_bc_addr = addr;
|
||||||
|
|
@ -36,22 +38,44 @@ task write_reg(
|
||||||
block_memory_tb.tb_bc_valid = 0;
|
block_memory_tb.tb_bc_valid = 0;
|
||||||
while (!block_memory_tb.bc_tb_valid) #`CP;
|
while (!block_memory_tb.bc_tb_valid) #`CP;
|
||||||
|
|
||||||
$display(" -> wrote 0x%h to addr 0x%h (%s)", data, addr, desc);
|
$display(" -> bus wrote 0x%h to addr 0x%h", data, addr);
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task write_and_verify(
|
task write_and_verify_bus_side(
|
||||||
input [15:0] addr,
|
input [15:0] addr,
|
||||||
input [15:0] write_data,
|
input [15:0] write_data
|
||||||
input string desc
|
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [15:0] read_data;
|
reg [15:0] read_data;
|
||||||
|
|
||||||
write_reg(addr, write_data, desc);
|
write_reg_bus_side(addr, write_data);
|
||||||
read_reg(addr, read_data, desc);
|
read_reg_bus_side(addr, read_data);
|
||||||
assert(read_data == write_data) else $error("data read does not match data written!");
|
assert(read_data == write_data) else $error("data read does not match data written!");
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
task read_user_side(
|
||||||
|
input [`ADDR_WIDTH-1:0] addr
|
||||||
|
);
|
||||||
|
|
||||||
|
block_memory_tb.bram_user_we = 0;
|
||||||
|
block_memory_tb.bram_user_addr = addr;
|
||||||
|
#(2*`CP);
|
||||||
|
$display("user read 0x%h from addr 0x%h", block_memory_tb.bram_user_dout, addr);
|
||||||
|
endtask
|
||||||
|
|
||||||
|
task write_user_side(
|
||||||
|
input [`ADDR_WIDTH-1:0] addr,
|
||||||
|
input [`BRAM_WIDTH-1:0] data
|
||||||
|
);
|
||||||
|
|
||||||
|
block_memory_tb.bram_user_we = 1;
|
||||||
|
block_memory_tb.bram_user_addr = addr;
|
||||||
|
block_memory_tb.bram_user_din = data;
|
||||||
|
#(2*`CP);
|
||||||
|
$display("user wrote 0x%h to addr 0x%h", data, addr);
|
||||||
|
endtask
|
||||||
|
|
||||||
|
|
||||||
module block_memory_tb;
|
module block_memory_tb;
|
||||||
|
|
||||||
// boilerplate
|
// boilerplate
|
||||||
|
|
@ -74,15 +98,15 @@ module block_memory_tb;
|
||||||
logic bc_tb_valid;
|
logic bc_tb_valid;
|
||||||
|
|
||||||
// bram itself
|
// bram itself
|
||||||
localparam BRAM_DEPTH = 256;
|
localparam BRAM_DEPTH = `BRAM_DEPTH;
|
||||||
localparam BRAM_WIDTH = 33;
|
localparam BRAM_WIDTH = `BRAM_WIDTH;
|
||||||
localparam ADDR_WIDTH = $clog2(BRAM_WIDTH);
|
localparam ADDR_WIDTH = $clog2(BRAM_DEPTH);
|
||||||
logic [ADDR_WIDTH-1:0] bram_user_addr = 0;
|
logic [ADDR_WIDTH-1:0] bram_user_addr = 0;
|
||||||
logic [BRAM_WIDTH-1:0] bram_user_din = 0;
|
logic [BRAM_WIDTH-1:0] bram_user_din = 0;
|
||||||
logic [BRAM_WIDTH-1:0] bram_user_dout;
|
logic [BRAM_WIDTH-1:0] bram_user_dout;
|
||||||
logic bram_user_we = 0;
|
logic bram_user_we = 0;
|
||||||
|
|
||||||
block_memory #(.BRAM_DEPTH(BRAM_DEPTH), .BRAM_WIDTH(BRAM_WIDTH)) my_bram_inst(
|
block_memory #(.DEPTH(BRAM_DEPTH), .WIDTH(BRAM_WIDTH)) block_mem (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
|
|
||||||
.addr_i(tb_bc_addr),
|
.addr_i(tb_bc_addr),
|
||||||
|
|
@ -112,8 +136,6 @@ module block_memory_tb;
|
||||||
$dumpfile("block_memory_tb.vcd");
|
$dumpfile("block_memory_tb.vcd");
|
||||||
$dumpvars(0, block_memory_tb);
|
$dumpvars(0, block_memory_tb);
|
||||||
|
|
||||||
$display("i am going to vomit %d", my_bram_inst.N_BRAMS);
|
|
||||||
|
|
||||||
// setup and reset
|
// setup and reset
|
||||||
clk = 0;
|
clk = 0;
|
||||||
test_num = 0;
|
test_num = 0;
|
||||||
|
|
@ -137,14 +159,22 @@ module block_memory_tb;
|
||||||
/* ==== Test 1 Begin ==== */
|
/* ==== Test 1 Begin ==== */
|
||||||
$display("\n=== test 1: read/write from BRAM, verify ===");
|
$display("\n=== test 1: read/write from BRAM, verify ===");
|
||||||
test_num = 1;
|
test_num = 1;
|
||||||
write_and_verify(3, 'h1234, "");
|
write_and_verify_bus_side(0, 'h6789);
|
||||||
write_and_verify(4, 'h5678, "");
|
write_and_verify_bus_side(1, 'h2345);
|
||||||
write_and_verify(5, 'h0001, "");
|
write_and_verify_bus_side(2, 'h0001);
|
||||||
|
|
||||||
// now query what's on the the user side at address 0
|
// now query what's on the the user side at address 0
|
||||||
bram_user_addr = 1;
|
read_user_side(0);
|
||||||
#(3*`CP);
|
|
||||||
$display("Found 0x%h on the other side", bram_user_dout);
|
write_and_verify_bus_side(3, 'h1111);
|
||||||
|
write_and_verify_bus_side(4, 'h1111);
|
||||||
|
write_and_verify_bus_side(5, 'h0001);
|
||||||
|
|
||||||
|
// now query what's on the the user side at address 0
|
||||||
|
read_user_side(1);
|
||||||
|
|
||||||
|
write_user_side(1, 0);
|
||||||
|
read_user_side(1);
|
||||||
|
|
||||||
#(10*`CP);
|
#(10*`CP);
|
||||||
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
module block_memory (
|
|
||||||
input wire clk,
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
|
|
||||||
// BRAM itself
|
|
||||||
input wire user_clk,
|
|
||||||
input wire [ADDR_WIDTH-1:0] user_addr,
|
|
||||||
input wire [BRAM_WIDTH-1:0] user_din,
|
|
||||||
output reg [BRAM_WIDTH-1:0] user_dout,
|
|
||||||
input wire user_we);
|
|
||||||
|
|
||||||
parameter BASE_ADDR = 0;
|
|
||||||
parameter BRAM_WIDTH = 0;
|
|
||||||
parameter BRAM_DEPTH = 0;
|
|
||||||
localparam ADDR_WIDTH = $clog2(BRAM_DEPTH);
|
|
||||||
|
|
||||||
// ugly typecasting, but just computes ceil(BRAM_WIDTH / 16)
|
|
||||||
localparam N_BRAMS = int'($ceil(real'(BRAM_WIDTH) / 16.0));
|
|
||||||
localparam MAX_ADDR = BASE_ADDR + (BRAM_DEPTH * N_BRAMS);
|
|
||||||
|
|
||||||
// Port A of BRAMs
|
|
||||||
reg [N_BRAMS-1:0][ADDR_WIDTH-1:0] addra = 0;
|
|
||||||
reg [N_BRAMS-1:0][15:0] dina = 0;
|
|
||||||
reg [N_BRAMS-1:0][15:0] douta;
|
|
||||||
reg [N_BRAMS-1:0] wea = 0;
|
|
||||||
|
|
||||||
// Port B of BRAMs
|
|
||||||
reg [N_BRAMS-1:0][15:0] dinb;
|
|
||||||
reg [N_BRAMS-1:0][15:0] doutb;
|
|
||||||
assign dinb = user_din;
|
|
||||||
|
|
||||||
// kind of a hack to part select from a 2d array that's been flattened to 1d
|
|
||||||
reg [(N_BRAMS*16)-1:0] doutb_flattened;
|
|
||||||
assign doutb_flattened = doutb;
|
|
||||||
assign user_dout = doutb_flattened[BRAM_WIDTH-1:0];
|
|
||||||
|
|
||||||
// Pipelining
|
|
||||||
reg [3:0][15:0] addr_pipe = 0;
|
|
||||||
reg [3:0][15:0] wdata_pipe = 0;
|
|
||||||
reg [3:0][15:0] rdata_pipe = 0;
|
|
||||||
reg [3:0] valid_pipe = 0;
|
|
||||||
reg [3:0] rw_pipe = 0;
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
addr_pipe[0] <= addr_i;
|
|
||||||
wdata_pipe[0] <= wdata_i;
|
|
||||||
rdata_pipe[0] <= rdata_i;
|
|
||||||
valid_pipe[0] <= valid_i;
|
|
||||||
rw_pipe[0] <= rw_i;
|
|
||||||
|
|
||||||
addr_o <= addr_pipe[2];
|
|
||||||
wdata_o <= wdata_pipe[2];
|
|
||||||
rdata_o <= rdata_pipe[2];
|
|
||||||
valid_o <= valid_pipe[2];
|
|
||||||
rw_o <= rw_pipe[2];
|
|
||||||
|
|
||||||
for(int i=1; i<4; i=i+1) begin
|
|
||||||
addr_pipe[i] <= addr_pipe[i-1];
|
|
||||||
wdata_pipe[i] <= wdata_pipe[i-1];
|
|
||||||
rdata_pipe[i] <= rdata_pipe[i-1];
|
|
||||||
valid_pipe[i] <= valid_pipe[i-1];
|
|
||||||
rw_pipe[i] <= rw_pipe[i-1];
|
|
||||||
end
|
|
||||||
|
|
||||||
// throw BRAM operations into the front of the pipeline
|
|
||||||
wea <= 0;
|
|
||||||
if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= MAX_ADDR)) begin
|
|
||||||
wea[addr_i % N_BRAMS] <= rw_i;
|
|
||||||
addra[addr_i % N_BRAMS] <= (addr_i - BASE_ADDR) / N_BRAMS;
|
|
||||||
dina[addr_i % N_BRAMS] <= wdata_i;
|
|
||||||
end
|
|
||||||
|
|
||||||
// pull BRAM reads from the back of the pipeline
|
|
||||||
if( (valid_pipe[2]) && (addr_pipe[2] >= BASE_ADDR) && (addr_pipe[2] <= MAX_ADDR)) begin
|
|
||||||
rdata_o <= douta[addr_pipe[2] % N_BRAMS];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// generate the BRAMs
|
|
||||||
genvar i;
|
|
||||||
generate
|
|
||||||
for(i=0; i<N_BRAMS; i=i+1) begin
|
|
||||||
dual_port_bram #(
|
|
||||||
.RAM_WIDTH(16),
|
|
||||||
.RAM_DEPTH(BRAM_DEPTH)
|
|
||||||
) bram_full_width_i (
|
|
||||||
|
|
||||||
// port A is controlled by the bus
|
|
||||||
.clka(clk),
|
|
||||||
.addra(addra[i]),
|
|
||||||
.dina(dina[i]),
|
|
||||||
.douta(douta[i]),
|
|
||||||
.wea(wea[i]),
|
|
||||||
|
|
||||||
// port B is exposed to the user
|
|
||||||
.clkb(user_clk),
|
|
||||||
.addrb(user_addr),
|
|
||||||
.dinb(dinb[i]),
|
|
||||||
.doutb(doutb[i]),
|
|
||||||
.web(user_we));
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
endmodule
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
from manta import Manta
|
|
||||||
m = Manta('manta.yaml')
|
|
||||||
|
|
||||||
bram_def = m.my_bram.hdl_def()
|
|
||||||
|
|
||||||
with open("block_memory.v", "w") as f:
|
|
||||||
f.write(bram_def)
|
|
||||||
|
|
||||||
print(m.my_bram.hdl_top_level_ports())
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
---
|
|
||||||
cores:
|
|
||||||
my_bram:
|
|
||||||
type: block_memory
|
|
||||||
width: 18
|
|
||||||
depth: 256
|
|
||||||
|
|
||||||
uart:
|
|
||||||
port: "auto"
|
|
||||||
baudrate: 115200
|
|
||||||
clock_freq: 100000000
|
|
||||||
Loading…
Reference in New Issue