HITDAQ/FPGA_firmware/q_sys/synthesis/submodules/algo_reconstruction_bkg.v
2024-10-11 14:49:54 +02:00

350 lines
8.7 KiB
Verilog

// the interface between sensor_interface and UDP
// with a sum_signal operation
// with background subtraction
// background info is in rom_bkg
`timescale 1 ps / 1 ps
module algo_reconstruction (
//Clock/reset
input wire clk_clk, // clk.clk
input wire rst_reset, // rst.reset
//Avalon ST receiver
(* keep *)input wire [31:0] data_in_data, // data_in.data
output wire data_in_ready, // .ready
input wire data_in_valid, // .valid
input wire [1:0] data_in_empty, // .empty
input wire data_in_endofpacket, // .endofpacket
input wire data_in_startofpacket, // .startofpacket
//Avalon ST transmitter
output wire [31:0] data_out_data, // avalon_streaming_source.data
output wire data_out_endofpacket, // .endofpacket
output wire data_out_startofpacket, // .startofpacket
input wire data_out_ready, // .ready
output wire data_out_valid, // .valid
output wire [1:0] data_out_empty // .empty
);
// *********************** Internal reset logic ************************
/*
The internal reset signal derives from the reset input).
It drives all subcomponents but registers (which use simpy the reset input).
This signal is registered to be sure that no glitches from register bank pass.
*/
reg int_rst;
always @(posedge clk_clk)
begin
int_rst <= rst_reset;
end
//Very important globals
reg[31:0] rx_buffer[162:0]; //Data to receive: 3 words header plus sensor data
wire start_transmission; //pulsing this signal causes the Avalon ST link to start transmission
reg[31:0] transmit_buffer[162:0]; //DATA to transmit, the last word is Sum_all.
//********************** Avalon receiver ************************
/*
The receiver is used to receive data from sensor interface
And a simple calculation
*/
reg [1:0] data_in_state;
localparam DATA_IN_STATE_IDLE = 0; //waiting for high
// localparam DATA_IN_VALID = 5; //valid wait for start packet
localparam DATA_IN_STATE_RECEIVE = 1; //receiving data
localparam DATA_IN_STATE_FINISH = 3; // finish and to copy data from rx_buffer to transmit_buffer;
localparam DATA_IN_STATE_LOCK_ALGO = 2; // leave for algorithm; currently
localparam WORDS_TO_RECEIVE = 163;
localparam WORDS_TO_SEND = 163;
integer i; //for generate loops
//registers to drive input pins of ST interfaces
reg reg_in_ready;
//Helper stuff
reg[15:0] rx_ctr; //counter of receive data worDS_TO_RECEIVE
// for sum
reg[31:0] sum_all; //
reg[31:0] sum_high;
reg[31:0] sum_low;
//the threshold bkg subtraction process
wire[31:0] channel_ctr; //channel_ctr<= 2*rx_ctr
reg[31:0] reg_channel_ctr;
assign channel_ctr = reg_channel_ctr;
//assign channel_ctr0 = rx_ctr<<1;
//assign channel_ctr1 = channel_ctr0 + 1'b1;
wire[31:0] bkg;
wire[31:0] wire_bkg;
wire[31:0] wire_rx_buffer; // the first 3 channel is data_in_data
wire[31:0] wire_for_sum; //the first 3 channel is 0
rom_bkg rom_bkg_inst (
.address_a ( channel_ctr[24:16]),
.address_b ( channel_ctr[8:0] ),
.clock ( clk_clk),
.q_a ( bkg[31:16]),
.q_b ( bkg[15:0])
);
// The state machine
always @(posedge clk_clk or posedge int_rst)
begin
if(int_rst)
begin
data_in_state <= DATA_IN_STATE_IDLE;
end
else
case(data_in_state)
DATA_IN_STATE_IDLE:
begin
if (data_in_valid & data_in_startofpacket)
begin
data_in_state <= DATA_IN_STATE_RECEIVE;
end
end
DATA_IN_STATE_RECEIVE:
begin
if (data_in_endofpacket)
begin
data_in_state <= DATA_IN_STATE_LOCK_ALGO;
end
end
DATA_IN_STATE_FINISH:
begin
data_in_state <= DATA_IN_STATE_IDLE;
end
DATA_IN_STATE_LOCK_ALGO:
begin
if (~data_in_valid)
data_in_state <= DATA_IN_STATE_FINISH;
end
default:
data_in_state <= DATA_IN_STATE_IDLE;
endcase
end
//Sequential Part for registers
always @(posedge clk_clk or posedge int_rst)
begin
if(int_rst)
begin
rx_ctr <= 0;
sum_all <= 0;
sum_high <= 0;
sum_low <= 0;
end
else
case(data_in_state)
DATA_IN_STATE_IDLE:
begin
rx_ctr <= 0;
sum_all <= 0;
sum_high <= 0;
sum_low <= 0;
end
DATA_IN_STATE_RECEIVE:
begin
rx_ctr <= rx_ctr + 1'b1;
reg_channel_ctr[31:16] <= rx_ctr << 1;
reg_channel_ctr[15:0] <= (rx_ctr << 1) + 1'b1;
rx_buffer[rx_ctr] <= wire_rx_buffer;
sum_high <= sum_high + wire_for_sum[31:16];
sum_low <= sum_low + wire_for_sum[15:0];
end
DATA_IN_STATE_FINISH:
begin
for (i = 0; i < (WORDS_TO_SEND-1); i = i+1)
begin
transmit_buffer[i] <= rx_buffer[i];
end
transmit_buffer[WORDS_TO_SEND-1] <= sum_all;// I should add one more state for sum_all
end
DATA_IN_STATE_LOCK_ALGO:
begin
sum_all <= sum_high + sum_low;
end
endcase
end
assign wire_bkg = ((rx_ctr == 0) |(rx_ctr == 1)| (rx_ctr == 2))? 0: bkg;
assign wire_rx_buffer = {data_in_data[31:16]-wire_bkg[31:16], data_in_data[15:0]-wire_bkg[15:0]};
assign wire_for_sum = ((rx_ctr == 0) |(rx_ctr == 1) | (rx_ctr == 2))?32'b0:wire_rx_buffer;
//Combinational Part
always @ (*)
begin
if (int_rst)
begin
reg_in_ready <= 0;
end
else
case(data_in_state)
DATA_IN_STATE_IDLE:
begin
reg_in_ready <= 0;
end
DATA_IN_STATE_RECEIVE:
begin
reg_in_ready <= 1;
end
DATA_IN_STATE_FINISH, DATA_IN_STATE_LOCK_ALGO:
begin
reg_in_ready <= 0;
end
default:
begin
reg_in_ready <= 0;
end
endcase
end
assign data_in_ready = reg_in_ready;
//Generate Avalon trigger signal
assign start_transmission = (data_in_state == DATA_IN_STATE_FINISH) ? 1 : 0;
// *********************** Avalon transmitter ************************
/*
The transmitter is used to transmit collected sensor data together with sync frame.
It can be later packed into UDP by UDP generator and sent over Ethernet. Or whatever.
The transmitter has 8-bit symbol, 4 symbols per beat. It's backpressurizable and includes packet signals.
The Empty signal is dummy (always zero), as the data is always aligned to 32-bit size.
The transmission starts when the 'start_transmission' signal gets pulsed
*/
assign data_out_empty = 2'b00;
reg [1:0] data_out_state; //State of the state machine
localparam DATA_OUT_STATE_IDLE = 0; //waiting for high
localparam DATA_OUT_STATE_SEND = 1; //sending data
localparam DATA_OUT_STATE_LOCK = 2; //waiting for trigger low
//registers to drive output pins of ST interfaces
reg reg_valid;
reg [31:0] reg_data;
reg reg_startofpacket;
reg reg_endofpacket;
//Helper stuff
reg [15:0] tx_ctr; //counter of sent data words
//The state machine
always @(posedge clk_clk or posedge int_rst)
begin
if (int_rst)
begin
data_out_state <= DATA_OUT_STATE_IDLE;
end
else
case(data_out_state)
DATA_OUT_STATE_IDLE:
begin
if (start_transmission)
begin
data_out_state <= DATA_OUT_STATE_SEND;
tx_ctr <= 0;
end
end
DATA_OUT_STATE_SEND:
begin
if (data_out_ready)
tx_ctr <= tx_ctr + 1;
if (tx_ctr == (WORDS_TO_SEND-1))
data_out_state <= DATA_OUT_STATE_LOCK;
end
DATA_OUT_STATE_LOCK:
begin
tx_ctr <= 0;
if (~start_transmission)
data_out_state <= DATA_OUT_STATE_IDLE;
end
default:
begin
data_out_state <= DATA_OUT_STATE_IDLE;
end
endcase
end
//Driving bus signals
always @( *)
begin
if (int_rst)
begin
reg_valid = 0;
reg_data = 0;
reg_startofpacket = 0;
reg_endofpacket = 0;
end
else
case(data_out_state)
DATA_OUT_STATE_IDLE, DATA_OUT_STATE_LOCK:
begin
reg_valid = 0;
reg_data = 0;
reg_startofpacket = 0;
reg_endofpacket = 0;
end
DATA_OUT_STATE_SEND:
begin
reg_data[31:0] = transmit_buffer[tx_ctr];
reg_valid = 1;
if (tx_ctr == 0)
reg_startofpacket = 1;
else
reg_startofpacket = 0;
if (tx_ctr == (WORDS_TO_SEND-1))
begin
reg_endofpacket = 1;
end
else
reg_endofpacket = 0;
end
default:
begin
reg_valid = 0;
reg_data = 0;
reg_startofpacket = 0;
reg_endofpacket = 0;
end
endcase
end
assign data_out_valid = reg_valid;
assign data_out_data = reg_data;
assign data_out_startofpacket = reg_startofpacket;
assign data_out_endofpacket = reg_endofpacket;
endmodule