accumulator's changes for dma integration
This commit is contained in:
+172
-48
@@ -5,7 +5,6 @@ module accumulator
|
|||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
parameter ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
parameter N_MAX = 4096,
|
parameter N_MAX = 4096,
|
||||||
parameter WINDOW_SIZE = 4,
|
|
||||||
parameter PACKET_SIZE = 8,
|
parameter PACKET_SIZE = 8,
|
||||||
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
||||||
)
|
)
|
||||||
@@ -17,15 +16,19 @@ module accumulator
|
|||||||
input start,
|
input start,
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input [15:0] seq_num,
|
input [15:0] seq_num,
|
||||||
|
input [31:0] window_size,
|
||||||
|
|
||||||
output [ACCUM_WIDTH-1:0] out_data,
|
output [ACCUM_WIDTH-1:0] out_data,
|
||||||
output out_valid,
|
output out_valid,
|
||||||
output readout_begin,
|
output readout_begin,
|
||||||
input batch_req,
|
input batch_req,
|
||||||
input finish
|
input finish,
|
||||||
|
|
||||||
|
output logic accum_done
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [31:0] smp_num_reg, cnt_smp_num;
|
logic [31:0] smp_num_reg, cnt_smp_num;
|
||||||
|
logic [31:0] window_size_reg;
|
||||||
logic [15:0] seq_num_reg, cnt_seq_num;
|
logic [15:0] seq_num_reg, cnt_seq_num;
|
||||||
logic [15:0] cnt_addr, addra, addrb;
|
logic [15:0] cnt_addr, addra, addrb;
|
||||||
|
|
||||||
@@ -39,10 +42,6 @@ module accumulator
|
|||||||
logic out_valid_reg;
|
logic out_valid_reg;
|
||||||
logic finish_reg, finish_buf;
|
logic finish_reg, finish_buf;
|
||||||
|
|
||||||
// registers for port b data request
|
|
||||||
reg req_data_b;
|
|
||||||
reg [15:0] req_addr_b;
|
|
||||||
|
|
||||||
typedef enum logic [3:0] {
|
typedef enum logic [3:0] {
|
||||||
IDLE,
|
IDLE,
|
||||||
INIT_MEM,
|
INIT_MEM,
|
||||||
@@ -58,18 +57,84 @@ module accumulator
|
|||||||
} wr_state_t;
|
} wr_state_t;
|
||||||
(* MARK_DEBUG="true" *) wr_state_t wr_state;
|
(* MARK_DEBUG="true" *) wr_state_t wr_state;
|
||||||
|
|
||||||
|
// One word per clock accumulation pipeline
|
||||||
|
// On every sum_valid in ACCUM we launch a BRAM read for cnt_addr
|
||||||
|
// On the next clock the saved sum_data is added to doutb and written back
|
||||||
|
logic accum_pipe_valid;
|
||||||
|
logic [15:0] accum_pipe_addr;
|
||||||
|
logic [ACCUM_WIDTH-1:0] accum_pipe_data;
|
||||||
|
|
||||||
|
// case smp_num // window_size == 1
|
||||||
|
// Then the next sequence can read the same address it is written
|
||||||
|
logic accum_pipe_bypass_valid;
|
||||||
|
logic [ACCUM_WIDTH-1:0] accum_pipe_bypass_data;
|
||||||
|
|
||||||
|
logic accum_accept_last;
|
||||||
|
logic accum_accept_last_all;
|
||||||
|
logic [ACCUM_WIDTH-1:0] accum_write_base;
|
||||||
|
logic [ACCUM_WIDTH-1:0] accum_write_value;
|
||||||
|
|
||||||
|
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
||||||
|
wire start_accept = start && (wr_state == IDLE);
|
||||||
|
|
||||||
|
assign accum_accept_last = (cnt_smp_num + window_size_reg >= smp_num_reg);
|
||||||
|
assign accum_accept_last_all = accum_accept_last && (cnt_seq_num == seq_num_reg - 1);
|
||||||
|
assign accum_write_base = accum_pipe_bypass_valid ? accum_pipe_bypass_data : data_bram_out;
|
||||||
|
assign accum_write_value = accum_pipe_data + accum_write_base;
|
||||||
|
|
||||||
|
// Memory controls to XPM
|
||||||
|
// In accumulation/init states they are driven directly from the current
|
||||||
|
// state and pipeline registers. That avoids an extra register stage
|
||||||
|
logic mem_wea;
|
||||||
|
logic mem_enb;
|
||||||
|
logic [15:0] mem_addra;
|
||||||
|
logic [15:0] mem_addrb;
|
||||||
|
logic [ACCUM_WIDTH-1:0] mem_dina;
|
||||||
|
|
||||||
|
assign mem_wea = (wr_state == INIT_MEM) ? valid_data :
|
||||||
|
(wr_state == ACCUM) ? accum_pipe_valid :
|
||||||
|
1'b0;
|
||||||
|
|
||||||
|
assign mem_addra = (wr_state == INIT_MEM) ? cnt_addr :
|
||||||
|
(wr_state == ACCUM) ? accum_pipe_addr :
|
||||||
|
addra;
|
||||||
|
|
||||||
|
assign mem_dina = (wr_state == INIT_MEM) ? data :
|
||||||
|
(wr_state == ACCUM) ? accum_write_value :
|
||||||
|
data_bram_in;
|
||||||
|
|
||||||
|
assign mem_enb = (wr_state == ACCUM) ? valid_data : enb;
|
||||||
|
assign mem_addrb = (wr_state == ACCUM) ? cnt_addr : addrb;
|
||||||
|
|
||||||
|
// registers for port b data request
|
||||||
|
reg req_data_b;
|
||||||
|
reg [15:0] req_addr_b;
|
||||||
|
|
||||||
always @(posedge clk_in) begin
|
always @(posedge clk_in) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
smp_num_reg <= '0;
|
smp_num_reg <= '0;
|
||||||
cnt_smp_num <= '0;
|
cnt_smp_num <= '0;
|
||||||
|
window_size_reg <= 32'd1;
|
||||||
seq_num_reg <= '0;
|
seq_num_reg <= '0;
|
||||||
cnt_seq_num <= '0;
|
cnt_seq_num <= '0;
|
||||||
cnt_addr <= '0;
|
cnt_addr <= '0;
|
||||||
|
addra <= '0;
|
||||||
|
addrb <= '0;
|
||||||
|
data_bram_in <= '0;
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
wr_state <= IDLE;
|
wr_state <= IDLE;
|
||||||
finish_reg <= 0;
|
finish_reg <= 0;
|
||||||
|
finish_buf <= 0;
|
||||||
|
readout_begin_reg <= 0;
|
||||||
|
out_data_reg <= '0;
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
|
accum_pipe_valid <= 0;
|
||||||
|
accum_pipe_addr <= '0;
|
||||||
|
accum_pipe_data <= '0;
|
||||||
|
accum_pipe_bypass_valid <= 0;
|
||||||
|
accum_pipe_bypass_data <= '0;
|
||||||
|
accum_done <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
finish_buf <= finish;
|
finish_buf <= finish;
|
||||||
|
|
||||||
@@ -83,83 +148,137 @@ module accumulator
|
|||||||
readout_begin_reg <= 0;
|
readout_begin_reg <= 0;
|
||||||
finish_reg <= 0;
|
finish_reg <= 0;
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
|
accum_pipe_valid <= 0;
|
||||||
|
accum_pipe_bypass_valid <= 0;
|
||||||
|
accum_done <= 0;
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
cnt_seq_num <= '0;
|
||||||
|
cnt_addr <= '0;
|
||||||
|
addrb <= '0;
|
||||||
if (start) begin
|
if (start) begin
|
||||||
smp_num_reg <= smp_num;
|
smp_num_reg <= smp_num;
|
||||||
seq_num_reg <= seq_num;
|
seq_num_reg <= seq_num;
|
||||||
|
window_size_reg <= window_size_safe;
|
||||||
wr_state <= INIT_MEM;
|
wr_state <= INIT_MEM;
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
INIT_MEM: begin
|
INIT_MEM: begin
|
||||||
// first run to initialize memory with first batch of values
|
// First sequence
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
|
enb <= 0;
|
||||||
|
out_valid_reg <= 0;
|
||||||
|
accum_pipe_valid <= 0;
|
||||||
|
accum_pipe_bypass_valid <= 0;
|
||||||
|
accum_done <= 0;
|
||||||
|
|
||||||
if (valid_data) begin
|
if (valid_data) begin
|
||||||
|
// mem_wea/mem_addra/mem_dina do the actual write in this clock
|
||||||
data_bram_in <= data;
|
data_bram_in <= data;
|
||||||
addra <= cnt_addr;
|
addra <= cnt_addr;
|
||||||
wea <= 1;
|
wea <= 1;
|
||||||
cnt_addr <= cnt_addr + 1;
|
|
||||||
cnt_smp_num <= cnt_smp_num + WINDOW_SIZE;
|
|
||||||
|
|
||||||
end
|
if (cnt_smp_num + window_size_reg >= smp_num_reg) begin
|
||||||
if (cnt_smp_num >= smp_num_reg) begin
|
cnt_smp_num <= '0;
|
||||||
wr_state <= BEGIN_SEQ;
|
cnt_addr <= '0;
|
||||||
end
|
|
||||||
|
|
||||||
end
|
if (seq_num_reg <= 16'd1) begin
|
||||||
BEGIN_SEQ: begin
|
|
||||||
// start new acc seq
|
|
||||||
wea <= 0;
|
|
||||||
enb <= 0;
|
|
||||||
if (cnt_seq_num == seq_num_reg - 1) begin
|
|
||||||
cnt_seq_num <= '0;
|
cnt_seq_num <= '0;
|
||||||
cnt_smp_num <= '0;
|
|
||||||
cnt_addr <= '0;
|
|
||||||
wr_state <= READOUT_START;
|
|
||||||
addrb <= '0;
|
addrb <= '0;
|
||||||
enb <= 0;
|
wr_state <= READOUT_START;
|
||||||
end else begin
|
end else begin
|
||||||
// beginning of new data sequence
|
// start further accumulation
|
||||||
cnt_seq_num <= cnt_seq_num + 1;
|
cnt_seq_num <= 16'd1;
|
||||||
cnt_smp_num <= '0;
|
wr_state <= ACCUM;
|
||||||
cnt_addr <= '0;
|
|
||||||
wea <= 0;
|
|
||||||
addrb <= 0;
|
|
||||||
wr_state <= REQ_WORD_B;
|
|
||||||
end
|
end
|
||||||
|
end else begin
|
||||||
|
cnt_smp_num <= cnt_smp_num + window_size_reg;
|
||||||
|
cnt_addr <= cnt_addr + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
BEGIN_SEQ: begin
|
||||||
|
// FIXME: unused
|
||||||
|
wea <= 0;
|
||||||
|
enb <= 0;
|
||||||
|
wr_state <= ACCUM;
|
||||||
end
|
end
|
||||||
|
|
||||||
REQ_WORD_B: begin
|
REQ_WORD_B: begin
|
||||||
// pre-request data for port b
|
// FIXME: depr
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
enb <= 1;
|
enb <= 0;
|
||||||
addrb <= cnt_addr;
|
|
||||||
wr_state <= ACCUM;
|
wr_state <= ACCUM;
|
||||||
end
|
end
|
||||||
|
|
||||||
ACCUM: begin
|
ACCUM: begin
|
||||||
// sum mem+input
|
// accum pipeline
|
||||||
|
wea <= 0;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
if (valid_data) begin
|
out_valid_reg <= 0;
|
||||||
addra <= cnt_addr;
|
|
||||||
|
if (accum_pipe_valid) begin
|
||||||
|
// mem_wea/mem_addra/mem_dina do the actual write this clock
|
||||||
|
addra <= accum_pipe_addr;
|
||||||
|
data_bram_in <= accum_write_value;
|
||||||
wea <= 1;
|
wea <= 1;
|
||||||
data_bram_in <= data + data_bram_out;
|
end
|
||||||
cnt_smp_num <= cnt_smp_num + WINDOW_SIZE;
|
|
||||||
if (cnt_smp_num + WINDOW_SIZE >= smp_num_reg) begin
|
if (accum_done) begin
|
||||||
wr_state <= BEGIN_SEQ;
|
// Last input word was accepted on the previous clk
|
||||||
|
accum_pipe_valid <= 0;
|
||||||
|
accum_pipe_bypass_valid <= 0;
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
cnt_seq_num <= '0;
|
||||||
|
cnt_addr <= '0;
|
||||||
|
addrb <= '0;
|
||||||
|
enb <= 0;
|
||||||
|
wr_state <= READOUT_START;
|
||||||
|
end else if (valid_data) begin
|
||||||
|
// mem_enb/mem_addrb launch the actual read this clock
|
||||||
|
enb <= 1;
|
||||||
|
addrb <= cnt_addr;
|
||||||
|
|
||||||
|
accum_pipe_valid <= 1;
|
||||||
|
accum_pipe_addr <= cnt_addr;
|
||||||
|
accum_pipe_data <= data;
|
||||||
|
|
||||||
|
// case window_size=1 && smp_num is small
|
||||||
|
accum_pipe_bypass_valid <= accum_pipe_valid && (accum_pipe_addr == cnt_addr);
|
||||||
|
accum_pipe_bypass_data <= accum_write_value;
|
||||||
|
|
||||||
|
if (accum_accept_last) begin
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
cnt_addr <= '0;
|
||||||
|
|
||||||
|
if (cnt_seq_num == seq_num_reg - 1) begin
|
||||||
|
accum_done <= 1;
|
||||||
end else begin
|
end else begin
|
||||||
|
cnt_seq_num <= cnt_seq_num + 1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
cnt_smp_num <= cnt_smp_num + window_size_reg;
|
||||||
cnt_addr <= cnt_addr + 1;
|
cnt_addr <= cnt_addr + 1;
|
||||||
wr_state <= REQ_WORD_B;
|
|
||||||
end
|
end
|
||||||
|
end else begin
|
||||||
|
accum_pipe_valid <= 0;
|
||||||
|
accum_pipe_bypass_valid <= 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
READOUT_START: begin
|
READOUT_START: begin
|
||||||
readout_begin_reg <= 1'b1;
|
readout_begin_reg <= 1'b1;
|
||||||
wr_state <= READOUT_AWAIT;
|
wr_state <= READOUT_AWAIT;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
|
wea <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
READOUT_AWAIT: begin
|
READOUT_AWAIT: begin
|
||||||
// req await + delay for every-clock readout.
|
// req await + delay for every-clock readout
|
||||||
|
wea <= 0;
|
||||||
if (batch_req) begin
|
if (batch_req) begin
|
||||||
enb <= 1;
|
enb <= 1;
|
||||||
wr_state <= READOUT_DELAY;
|
wr_state <= READOUT_DELAY;
|
||||||
@@ -173,12 +292,14 @@ module accumulator
|
|||||||
|
|
||||||
READOUT_DELAY: begin
|
READOUT_DELAY: begin
|
||||||
// wait for mem latency
|
// wait for mem latency
|
||||||
|
wea <= 0;
|
||||||
addrb <= addrb + 1;
|
addrb <= addrb + 1;
|
||||||
wr_state <= READOUT_PUT;
|
wr_state <= READOUT_PUT;
|
||||||
end
|
end
|
||||||
|
|
||||||
READOUT_PUT: begin
|
READOUT_PUT: begin
|
||||||
// main data output
|
// main data output
|
||||||
|
wea <= 0;
|
||||||
if ((addrb % READ_BATCH_SIZE) == 0) begin
|
if ((addrb % READ_BATCH_SIZE) == 0) begin
|
||||||
wr_state <= READOUT_LAST;
|
wr_state <= READOUT_LAST;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
@@ -190,6 +311,7 @@ module accumulator
|
|||||||
|
|
||||||
READOUT_LAST: begin
|
READOUT_LAST: begin
|
||||||
// last word of packet
|
// last word of packet
|
||||||
|
wea <= 0;
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
out_data_reg <= data_bram_out;
|
out_data_reg <= data_bram_out;
|
||||||
wr_state <= READOUT_START;
|
wr_state <= READOUT_START;
|
||||||
@@ -198,6 +320,7 @@ module accumulator
|
|||||||
FINISH: begin
|
FINISH: begin
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
|
wea <= 0;
|
||||||
wr_state <= IDLE;
|
wr_state <= IDLE;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -210,12 +333,13 @@ module accumulator
|
|||||||
adder
|
adder
|
||||||
#(
|
#(
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
.WINDOW_SIZE(WINDOW_SIZE),
|
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH)
|
.ACCUM_WIDTH(ACCUM_WIDTH)
|
||||||
) adder_dut
|
) adder_dut
|
||||||
(
|
(
|
||||||
.clk_in(clk_in),
|
.clk_in(clk_in),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
|
.start(start_accept),
|
||||||
|
.window_size(window_size),
|
||||||
.s_axis_tdata(s_axis_tdata),
|
.s_axis_tdata(s_axis_tdata),
|
||||||
.s_axis_tvalid(s_axis_tvalid),
|
.s_axis_tvalid(s_axis_tvalid),
|
||||||
.sum_data(data),
|
.sum_data(data),
|
||||||
@@ -254,14 +378,14 @@ module accumulator
|
|||||||
|
|
||||||
.doutb(data_bram_out),
|
.doutb(data_bram_out),
|
||||||
|
|
||||||
.addra(addra),
|
.addra(mem_addra),
|
||||||
.addrb(addrb),
|
.addrb(mem_addrb),
|
||||||
.clka(clk_in),
|
.clka(clk_in),
|
||||||
.clkb(clk_in),
|
.clkb(clk_in),
|
||||||
.dina(data_bram_in),
|
.dina(mem_dina),
|
||||||
.ena(1'b1),
|
.ena(1'b1),
|
||||||
.enb(enb),
|
.enb(mem_enb),
|
||||||
.wea(wea)
|
.wea(mem_wea)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign readout_begin = readout_begin_reg;
|
assign readout_begin = readout_begin_reg;
|
||||||
|
|||||||
+47
-18
@@ -5,7 +5,6 @@ module accumulator_top
|
|||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
parameter ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
parameter N_MAX = 4096,
|
parameter N_MAX = 4096,
|
||||||
parameter WINDOW_SIZE = 65,
|
|
||||||
parameter PACKET_SIZE = 1024,
|
parameter PACKET_SIZE = 1024,
|
||||||
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
||||||
)
|
)
|
||||||
@@ -22,19 +21,17 @@ module accumulator_top
|
|||||||
input start,
|
input start,
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input [15:0] seq_num,
|
input [15:0] seq_num,
|
||||||
|
input [31:0] window_size,
|
||||||
|
|
||||||
// eth signals
|
// eth signals
|
||||||
input eth_clk_in,
|
input dma_clk_in,
|
||||||
input req_ready,
|
input req_ready,
|
||||||
output send_req,
|
output send_req,
|
||||||
|
|
||||||
// output axis
|
// output axis
|
||||||
output logic [7:0] m_axis_tdata,
|
axis_if.master m_axis_accum,
|
||||||
output logic m_axis_tvalid,
|
output logic finish,
|
||||||
input logic m_axis_tready,
|
output logic accum_done
|
||||||
output logic m_axis_tlast,
|
|
||||||
|
|
||||||
output logic finish
|
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [ACCUM_WIDTH-1:0] out_data;
|
wire [ACCUM_WIDTH-1:0] out_data;
|
||||||
@@ -42,41 +39,73 @@ module accumulator_top
|
|||||||
wire readout_begin;
|
wire readout_begin;
|
||||||
wire batch_req;
|
wire batch_req;
|
||||||
|
|
||||||
|
logic finish_int;
|
||||||
|
logic finish_int_d;
|
||||||
|
logic finish_pulse;
|
||||||
|
logic calc_active;
|
||||||
|
logic start_accept;
|
||||||
|
logic [31:0] window_size_reg;
|
||||||
|
|
||||||
|
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
||||||
|
|
||||||
|
assign finish_pulse = finish_int && !finish_int_d;
|
||||||
|
assign start_accept = start && !calc_active;
|
||||||
|
assign finish = finish_int;
|
||||||
|
|
||||||
|
// Keep the top copy stable for blocks that start later than the accum itself
|
||||||
|
always_ff @(posedge clk_in) begin
|
||||||
|
if (rst) begin
|
||||||
|
calc_active <= 1'b0;
|
||||||
|
finish_int_d <= 1'b0;
|
||||||
|
window_size_reg <= 32'd1;
|
||||||
|
end else begin
|
||||||
|
finish_int_d <= finish_int;
|
||||||
|
|
||||||
|
if (start_accept) begin
|
||||||
|
calc_active <= 1'b1;
|
||||||
|
window_size_reg <= window_size_safe;
|
||||||
|
end else if (finish_pulse) begin
|
||||||
|
calc_active <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
accumulator #(
|
accumulator #(
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||||
.N_MAX(N_MAX),
|
.N_MAX(N_MAX),
|
||||||
.WINDOW_SIZE(WINDOW_SIZE),
|
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
.PACKET_SIZE(PACKET_SIZE)
|
||||||
) accum_main (
|
) accum_main (
|
||||||
.clk_in(clk_in),
|
.clk_in(clk_in),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
.s_axis_tdata(s_axis_tdata),
|
.s_axis_tdata(s_axis_tdata),
|
||||||
.s_axis_tvalid(s_axis_tvalid),
|
.s_axis_tvalid(s_axis_tvalid),
|
||||||
.start(start),
|
.start(start_accept),
|
||||||
.smp_num(smp_num),
|
.smp_num(smp_num),
|
||||||
.seq_num(seq_num),
|
.seq_num(seq_num),
|
||||||
|
.window_size(window_size),
|
||||||
.out_data(out_data),
|
.out_data(out_data),
|
||||||
.out_valid(out_valid),
|
.out_valid(out_valid),
|
||||||
.readout_begin(readout_begin),
|
.readout_begin(readout_begin),
|
||||||
.batch_req(batch_req),
|
.batch_req(batch_req),
|
||||||
.finish(finish)
|
.finish(finish_int),
|
||||||
|
.accum_done(accum_done)
|
||||||
);
|
);
|
||||||
|
|
||||||
out_axis_fifo #(
|
out_axis_fifo #(
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||||
.WINDOW_SIZE(WINDOW_SIZE),
|
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
.PACKET_SIZE(PACKET_SIZE)
|
||||||
) output_async_fifo (
|
) output_async_fifo (
|
||||||
.eth_clk_in (eth_clk_in),
|
.dma_clk_in (dma_clk_in),
|
||||||
.acc_clk_in (clk_in),
|
.acc_clk_in (clk_in),
|
||||||
.rst (rst),
|
.rst (rst),
|
||||||
.smp_num (smp_num),
|
.smp_num (smp_num),
|
||||||
|
.window_size (window_size_reg),
|
||||||
|
|
||||||
.m_axis_tdata (m_axis_tdata),
|
.m_axis_tdata (m_axis_accum.req.t.data),
|
||||||
.m_axis_tvalid (m_axis_tvalid),
|
.m_axis_tvalid (m_axis_accum.req.t.valid),
|
||||||
.m_axis_tready (m_axis_tready),
|
.m_axis_tready (m_axis_accum.resp.ready),
|
||||||
.m_axis_tlast (m_axis_tlast),
|
.m_axis_tlast (m_axis_accum.req.t.last),
|
||||||
|
|
||||||
.acc_din (out_data),
|
.acc_din (out_data),
|
||||||
.din_valid (out_valid),
|
.din_valid (out_valid),
|
||||||
@@ -87,6 +116,6 @@ module accumulator_top
|
|||||||
.send_req (send_req),
|
.send_req (send_req),
|
||||||
|
|
||||||
.batch_req (batch_req),
|
.batch_req (batch_req),
|
||||||
.finish (finish)
|
.finish (finish_int)
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
||||||
+20
-3
@@ -4,12 +4,13 @@
|
|||||||
module adder
|
module adder
|
||||||
#(
|
#(
|
||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
parameter WINDOW_SIZE = 4,
|
|
||||||
parameter ACCUM_WIDTH = 32
|
parameter ACCUM_WIDTH = 32
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input clk_in,
|
input clk_in,
|
||||||
input rst,
|
input rst,
|
||||||
|
input start,
|
||||||
|
input [31:0] window_size,
|
||||||
input [DATA_WIDTH-1:0] s_axis_tdata,
|
input [DATA_WIDTH-1:0] s_axis_tdata,
|
||||||
input s_axis_tvalid,
|
input s_axis_tvalid,
|
||||||
|
|
||||||
@@ -20,7 +21,10 @@ module adder
|
|||||||
logic [ACCUM_WIDTH-1:0] accum, res;
|
logic [ACCUM_WIDTH-1:0] accum, res;
|
||||||
logic [DATA_WIDTH-1:0] axis_data;
|
logic [DATA_WIDTH-1:0] axis_data;
|
||||||
logic res_valid, axis_valid;
|
logic res_valid, axis_valid;
|
||||||
(* MARK_DEBUG = "TRUE" *) logic [15:0] cnt;
|
(* MARK_DEBUG = "TRUE" *) logic [31:0] cnt;
|
||||||
|
logic [31:0] window_size_reg;
|
||||||
|
|
||||||
|
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
||||||
|
|
||||||
always @(posedge clk_in) begin
|
always @(posedge clk_in) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
@@ -28,12 +32,24 @@ module adder
|
|||||||
cnt <= '0;
|
cnt <= '0;
|
||||||
res <= '0;
|
res <= '0;
|
||||||
res_valid <= 0;
|
res_valid <= 0;
|
||||||
|
axis_data <= '0;
|
||||||
|
axis_valid <= 0;
|
||||||
|
window_size_reg <= 32'd1;
|
||||||
end else begin
|
end else begin
|
||||||
res_valid <= 0;
|
res_valid <= 0;
|
||||||
|
|
||||||
|
if (start) begin
|
||||||
|
accum <= '0;
|
||||||
|
cnt <= '0;
|
||||||
|
res <= '0;
|
||||||
|
axis_data <= '0;
|
||||||
|
axis_valid <= 0;
|
||||||
|
window_size_reg <= window_size_safe;
|
||||||
|
end else begin
|
||||||
axis_data <= s_axis_tdata;
|
axis_data <= s_axis_tdata;
|
||||||
axis_valid <= s_axis_tvalid;
|
axis_valid <= s_axis_tvalid;
|
||||||
if (axis_valid) begin
|
if (axis_valid) begin
|
||||||
if (cnt == WINDOW_SIZE-1) begin
|
if (cnt == window_size_reg - 1) begin
|
||||||
res <= accum + axis_data;
|
res <= accum + axis_data;
|
||||||
res_valid <= 1;
|
res_valid <= 1;
|
||||||
accum <= '0;
|
accum <= '0;
|
||||||
@@ -45,6 +61,7 @@ module adder
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
assign sum_valid = res_valid;
|
assign sum_valid = res_valid;
|
||||||
assign sum_data = res;
|
assign sum_data = res;
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
module out_axis_fifo #(
|
module out_axis_fifo #(
|
||||||
parameter ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
parameter WINDOW_SIZE = 65,
|
parameter RW_WIDTH = 32,
|
||||||
parameter PACKET_SIZE = 1024
|
parameter PACKET_SIZE = 1024
|
||||||
) (
|
) (
|
||||||
input logic eth_clk_in,
|
input logic dma_clk_in,
|
||||||
input logic acc_clk_in,
|
input logic acc_clk_in,
|
||||||
input logic rst,
|
input logic rst,
|
||||||
input logic [31:0] smp_num,
|
input logic [31:0] smp_num,
|
||||||
|
input logic [31:0] window_size,
|
||||||
|
|
||||||
// AXI stream master for output, eth_clk_in domain
|
// AXI stream master for output, dma_clk_in domain
|
||||||
output logic [7:0] m_axis_tdata,
|
output logic [RW_WIDTH:0] m_axis_tdata,
|
||||||
output logic m_axis_tvalid,
|
output logic m_axis_tvalid,
|
||||||
input logic m_axis_tready,
|
input logic m_axis_tready,
|
||||||
output logic m_axis_tlast,
|
output logic m_axis_tlast,
|
||||||
@@ -64,7 +65,7 @@ module out_axis_fifo #(
|
|||||||
localparam int WDEPTH_BITS = $clog2(MIN_WR_WORDS);
|
localparam int WDEPTH_BITS = $clog2(MIN_WR_WORDS);
|
||||||
localparam int FIFO_WDEPTH = 1 << WDEPTH_BITS;
|
localparam int FIFO_WDEPTH = 1 << WDEPTH_BITS;
|
||||||
|
|
||||||
localparam int FIFO_RDEPTH = FIFO_WDEPTH * ACCUM_WIDTH / 8;
|
localparam int FIFO_RDEPTH = FIFO_WDEPTH * ACCUM_WIDTH / RW_WIDTH;
|
||||||
localparam int RDEPTH_BITS = $clog2(FIFO_RDEPTH) + 1;
|
localparam int RDEPTH_BITS = $clog2(FIFO_RDEPTH) + 1;
|
||||||
|
|
||||||
wire wr_unavail;
|
wire wr_unavail;
|
||||||
@@ -85,6 +86,8 @@ module out_axis_fifo #(
|
|||||||
reg [31:0] wr_cnt; // current BIT mem ptr
|
reg [31:0] wr_cnt; // current BIT mem ptr
|
||||||
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
||||||
reg [31:0] wr_total; // total BITS to be sent!
|
reg [31:0] wr_total; // total BITS to be sent!
|
||||||
|
logic [31:0] window_size_reg;
|
||||||
|
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
||||||
|
|
||||||
wire empty;
|
wire empty;
|
||||||
|
|
||||||
@@ -92,7 +95,7 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// each written "acc_din" ACCUM_WIDTH word
|
// each written "acc_din" ACCUM_WIDTH word
|
||||||
// is counted as WINDOWS_SIZE samples actually
|
// is counted as window_size samples actually
|
||||||
// because hw division for counters is painful
|
// because hw division for counters is painful
|
||||||
// so we just increased the counter sizes
|
// so we just increased the counter sizes
|
||||||
|
|
||||||
@@ -102,6 +105,7 @@ module out_axis_fifo #(
|
|||||||
wr_cnt <= 32'b0;
|
wr_cnt <= 32'b0;
|
||||||
wr_batch_tgt <= 32'b0;
|
wr_batch_tgt <= 32'b0;
|
||||||
wr_total <= 32'b0;
|
wr_total <= 32'b0;
|
||||||
|
window_size_reg <= 32'd1;
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
finish <= 0;
|
finish <= 0;
|
||||||
|
|
||||||
@@ -115,6 +119,7 @@ module out_axis_fifo #(
|
|||||||
wr_state <= WR_CHECK;
|
wr_state <= WR_CHECK;
|
||||||
wr_total <= smp_num * ACCUM_WIDTH;
|
wr_total <= smp_num * ACCUM_WIDTH;
|
||||||
wr_batch_tgt <= 32'b0;
|
wr_batch_tgt <= 32'b0;
|
||||||
|
window_size_reg <= window_size_safe;
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
finish <= 0;
|
finish <= 0;
|
||||||
end
|
end
|
||||||
@@ -126,9 +131,9 @@ module out_axis_fifo #(
|
|||||||
if ((wr_data_count < (FIFO_WDEPTH - (PACKET_SIZE / (ACCUM_WIDTH / 8)))) && ~wr_rst_busy) begin
|
if ((wr_data_count < (FIFO_WDEPTH - (PACKET_SIZE / (ACCUM_WIDTH / 8)))) && ~wr_rst_busy) begin
|
||||||
batch_req <= 1;
|
batch_req <= 1;
|
||||||
// should give us exactly PACKET_SIZE * 8 bits
|
// should give us exactly PACKET_SIZE * 8 bits
|
||||||
// multiplied by WINDOW_SIZE, because we count
|
// multiplied by window_size, because we count
|
||||||
// each given ACCUM_WIDTH word as WINDOWS_SIZE samples !!!
|
// each given ACCUM_WIDTH word as window_size samples !!!
|
||||||
wr_batch_tgt <= wr_batch_tgt + (8 * WINDOW_SIZE * PACKET_SIZE);
|
wr_batch_tgt <= wr_batch_tgt + (8 * window_size_reg * PACKET_SIZE);
|
||||||
wr_state <= WR_RUN;
|
wr_state <= WR_RUN;
|
||||||
end else begin
|
end else begin
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
@@ -150,8 +155,8 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
if (din_valid) begin
|
if (din_valid) begin
|
||||||
// data supplied
|
// data supplied
|
||||||
// count as we got WINDOW_SIZE samples
|
// count as we got window_size samples
|
||||||
wr_cnt <= wr_cnt + ACCUM_WIDTH * WINDOW_SIZE;
|
wr_cnt <= wr_cnt + ACCUM_WIDTH * window_size_reg;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -190,7 +195,7 @@ module out_axis_fifo #(
|
|||||||
wire rd_valid;
|
wire rd_valid;
|
||||||
wire [RDEPTH_BITS-1:0] rd_data_count;
|
wire [RDEPTH_BITS-1:0] rd_data_count;
|
||||||
|
|
||||||
always_ff @(posedge eth_clk_in) begin
|
always_ff @(posedge dma_clk_in) begin
|
||||||
if (rst_eth) begin
|
if (rst_eth) begin
|
||||||
rd_state <= RD_IDLE;
|
rd_state <= RD_IDLE;
|
||||||
send_req <= 1'b0;
|
send_req <= 1'b0;
|
||||||
@@ -307,7 +312,7 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
.rd_clk(eth_clk_in), // 1-bit input: Read clock: Used for read operation. rd_clk must be a free running clock.
|
.rd_clk(dma_clk_in), // 1-bit input: Read clock: Used for read operation. rd_clk must be a free running clock.
|
||||||
.rd_en(rd_en), // 1-bit input: Read Enable: If the FIFO is not empty, asserting this signal causes data (on dout) to be read
|
.rd_en(rd_en), // 1-bit input: Read Enable: If the FIFO is not empty, asserting this signal causes data (on dout) to be read
|
||||||
// from the FIFO. Must be held active-low when rd_rst_busy is active high.
|
// from the FIFO. Must be held active-low when rd_rst_busy is active high.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user