350 lines
8.7 KiB
Verilog
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
|