330 lines
8.0 KiB
Verilog
330 lines
8.0 KiB
Verilog
// sum_interface.v
|
|
|
|
|
|
|
|
`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
|
|
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 receiveing to run algorithm
|
|
localparam DATA_IN_STATE_LOCK = 2; //roll to IDLE
|
|
|
|
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
|
|
reg[31:0] sum_all; //
|
|
reg[31:0] sum_high;
|
|
reg[31:0] sum_low;
|
|
|
|
|
|
|
|
//the threshold bkg subtraction process
|
|
wire[15:0] channel_ctr0; //channel_ctr<= 2*rx_ctr -6
|
|
wire[15:0] channel_ctr1;
|
|
assign channel_ctr0 = (rx_ctr>2'b00)? (((rx_ctr-2'b01)<<1)): 16'h1FE;
|
|
assign channel_ctr1 = channel_ctr0 + 1'b1;
|
|
wire[15:0] bkg0;
|
|
wire[15:0] bkg1;
|
|
|
|
//bkg bkg_inst0(
|
|
// .address ( channel_ctr0[8:0]),
|
|
// .clock ( clk_clk),
|
|
// .q ( bkg0)
|
|
// );
|
|
//
|
|
//bkg bkg_inst1(
|
|
// .address ( channel_ctr1[8:0]),
|
|
// .clock ( clk_clk),
|
|
// .q ( bkg1)
|
|
// );
|
|
//
|
|
|
|
rom_bkg rom_bkg_inst (
|
|
.address_a ( channel_ctr0[8:0] ),
|
|
.address_b ( channel_ctr1[8:0] ),
|
|
.clock ( clk_clk),
|
|
.q_a ( bkg0),
|
|
.q_b ( bkg1)
|
|
);
|
|
|
|
|
|
// The state machine
|
|
always @(posedge clk_clk or posedge int_rst)
|
|
begin
|
|
if(int_rst)
|
|
begin
|
|
data_in_state <= DATA_IN_STATE_IDLE;
|
|
sum_all <= 0;
|
|
sum_high <= 0;
|
|
sum_low <= 0;
|
|
end
|
|
else
|
|
case(data_in_state)
|
|
DATA_IN_STATE_IDLE:
|
|
begin
|
|
if (data_in_valid)
|
|
begin
|
|
data_in_state <= DATA_IN_STATE_RECEIVE;
|
|
rx_ctr <= 0;
|
|
sum_all <= 0;
|
|
sum_high <= 0;
|
|
sum_low <= 0;
|
|
end
|
|
end
|
|
DATA_IN_STATE_RECEIVE:
|
|
begin
|
|
if (data_in_valid & data_in_ready)
|
|
begin
|
|
rx_ctr <= rx_ctr+1;
|
|
sum_high <= sum_high + data_in_data[31:16];
|
|
sum_low <= sum_low+ data_in_data[15:0];
|
|
|
|
end
|
|
|
|
if (rx_ctr == (WORDS_TO_RECEIVE-1))
|
|
begin
|
|
data_in_state <= DATA_IN_STATE_FINISH;
|
|
sum_all <= sum_low +sum_high;
|
|
end
|
|
end
|
|
DATA_IN_STATE_FINISH:
|
|
begin
|
|
data_in_state <= DATA_IN_STATE_LOCK;
|
|
rx_ctr <= 0;
|
|
end
|
|
DATA_IN_STATE_LOCK:
|
|
begin
|
|
if (~data_in_valid)
|
|
data_in_state <= DATA_IN_STATE_IDLE;
|
|
end
|
|
|
|
default:
|
|
data_in_state <= DATA_IN_STATE_IDLE;
|
|
endcase
|
|
end
|
|
|
|
//Combinational Part
|
|
|
|
always @ (*)
|
|
begin
|
|
if (int_rst)
|
|
begin
|
|
reg_in_ready <= 0;
|
|
end
|
|
else
|
|
case(data_in_state)
|
|
DATA_IN_STATE_IDLE, DATA_IN_STATE_LOCK:
|
|
begin
|
|
reg_in_ready <= 0;
|
|
end
|
|
DATA_IN_STATE_RECEIVE:
|
|
begin
|
|
if (data_in_startofpacket)
|
|
reg_in_ready <= 1;
|
|
if (data_in_ready)
|
|
rx_buffer[rx_ctr] <= (rx_ctr>2'b10)?{data_in_data[31:16]-bkg0, data_in_data[15:0]-bkg1}:data_in_data[31:0];
|
|
end
|
|
DATA_IN_STATE_FINISH:
|
|
begin
|
|
reg_in_ready <= 0;
|
|
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;
|
|
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)
|
|
data_out_state <= DATA_OUT_STATE_IDLE;
|
|
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:
|
|
data_out_state <= DATA_OUT_STATE_IDLE;
|
|
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_valid = 1;
|
|
reg_data[31:0] = transmit_buffer[tx_ctr];
|
|
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
|