218 lines
6.7 KiB
Coq
218 lines
6.7 KiB
Coq
|
//background subtraction module
|
||
|
|
||
|
//tested with bkg_subtraction_tb.v
|
||
|
module bkg_subtraction #(parameter BKG_FRAME = 4)(
|
||
|
|
||
|
//clock and reset
|
||
|
input wire clk,
|
||
|
input wire rst, // connect to rst_run
|
||
|
|
||
|
//avalon ST(Streaming) sink: 0 readlatency and 0 readallowence // 163 word = 3 header + 160 data
|
||
|
input wire [31:0] data_in_data, // st.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(Streaming) source: 0 readlatency and 0 readallowence //160 word only with data
|
||
|
output wire [31:0] data_out_data, // st.data
|
||
|
input wire data_out_ready, // .ready
|
||
|
output wire data_out_valid, // .valid
|
||
|
output wire [1:0] data_out_empty, // .empty
|
||
|
output wire data_out_endofpacket, // .endofpacket
|
||
|
output wire data_out_startofpacket // .startofpacket
|
||
|
|
||
|
//output rst_frame // I have to think about this rst_frame when is a good timing! or do I need it? 26.June. 2024
|
||
|
);
|
||
|
|
||
|
wire bkg_sub_on;
|
||
|
wire rst_frame = data_in_startofpacket;
|
||
|
|
||
|
/************************* Frame Counter***********************************/
|
||
|
/*
|
||
|
This is a frame counter;
|
||
|
frameID +1 at the rising edge of data_in_startofpacket
|
||
|
if frame increase at 10kHz, the 27-bit frameID can count 3.72 hour frame
|
||
|
*/
|
||
|
reg [26:0] frameID;
|
||
|
reg data_in_startofpacket_last;
|
||
|
|
||
|
always @(posedge clk or posedge rst)
|
||
|
begin
|
||
|
if (rst)
|
||
|
begin
|
||
|
data_in_startofpacket_last <= 1'b0;
|
||
|
frameID<= 27'b0;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
data_in_startofpacket_last <= data_in_startofpacket;
|
||
|
if (~data_in_startofpacket_last && data_in_startofpacket)
|
||
|
frameID<= frameID + 1'b1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
// *********************** ST interface ***********************
|
||
|
|
||
|
reg [4:0] state; //State of the state machine
|
||
|
localparam STATE_IDLE = 5'd0; //waiting for SOP
|
||
|
localparam STATE_WORD0 = 5'd1; //sending first word :
|
||
|
localparam STATE_WORD1 = 5'd2; //sending second word:
|
||
|
localparam STATE_WORD2 = 5'd3; //sending third word :
|
||
|
localparam STATE_DATA_PRO = 5'd4; //blocking data get bkg_signal; and do the subtraction
|
||
|
localparam STATE_DATA_NEXT = 5'd7; //sending data
|
||
|
localparam STATE_LOC = 5'd5; //calculatebb
|
||
|
|
||
|
|
||
|
//Helper stuff
|
||
|
reg [7:0] tx_ctr; //counter of sent data words range: 0~255
|
||
|
localparam WORDS_TO_SEND = 163;
|
||
|
|
||
|
//the number of clocks for STATE_DATA_PRO
|
||
|
reg [5:0] delay_ctr;
|
||
|
localparam DELAY_CLOCKS = 6'd2;
|
||
|
|
||
|
/************** bkg RAM ****************************/
|
||
|
/*
|
||
|
for prepare the bkg signal by two RAM;
|
||
|
one for data_in_data[31:16]; the other for data_in_data[15:0]
|
||
|
the signal after bkg subtraction is 16 bit signed; the LSM bit is dropped out; (it's not important with current noise level)
|
||
|
*/
|
||
|
|
||
|
wire[15:0] bkgH;
|
||
|
wire[15:0] bkgL;
|
||
|
|
||
|
wire[31:0] bkg_input_data;
|
||
|
wire bkg_input_valid;
|
||
|
assign bkg_input_valid = (state == STATE_DATA_NEXT && data_out_ready);
|
||
|
//assign bkg_input_valid = 1'b1;
|
||
|
|
||
|
//signal after subtract background
|
||
|
//got the background signal at the third clock in STATE_DATA_PRO
|
||
|
//and subtract it to 16 bit by giving up the LSM, i.e. divide 2.
|
||
|
reg [16:0] signal0_17bit;
|
||
|
reg [16:0] signal1_17bit;
|
||
|
wire[15:0] signal0;
|
||
|
wire[15:0] signal1;
|
||
|
|
||
|
assign signal0 = bkg_sub_on?signal0_17bit[16:1]:signal0_17bit[15:0];
|
||
|
assign signal1 = bkg_sub_on?signal1_17bit[16:1]:signal1_17bit[15:0];
|
||
|
|
||
|
bkg_ram #(.TOTAL_FRAME(BKG_FRAME)) bkg_ram0(
|
||
|
.clk_clk(clk),
|
||
|
.rst_reset(rst),
|
||
|
.frameID(frameID[26:0]),
|
||
|
.address(tx_ctr),
|
||
|
.data_in_data(bkg_input_data),
|
||
|
.data_in_valid(bkg_input_valid),
|
||
|
.bkg_signal({bkgH,bkgL}),
|
||
|
.bkg_sub_status(bkg_sub_on)
|
||
|
);
|
||
|
|
||
|
assign bkg_input_data = (state==STATE_DATA_NEXT)?data_in_data:15'b0;
|
||
|
|
||
|
wire data_out_ready_for3header = 1'b1;
|
||
|
//The state machine
|
||
|
always @(posedge clk or posedge rst)
|
||
|
begin
|
||
|
if (rst)
|
||
|
begin
|
||
|
state <= STATE_IDLE;
|
||
|
end
|
||
|
else
|
||
|
case(state)
|
||
|
STATE_IDLE:
|
||
|
begin
|
||
|
if (data_in_startofpacket)
|
||
|
begin
|
||
|
state <= STATE_WORD0;
|
||
|
tx_ctr <= 0;
|
||
|
end
|
||
|
end
|
||
|
STATE_WORD0:
|
||
|
begin
|
||
|
if (data_in_valid && data_out_ready_for3header)
|
||
|
begin
|
||
|
state <= STATE_WORD1;
|
||
|
tx_ctr <= tx_ctr+ 1'b1;
|
||
|
end
|
||
|
end
|
||
|
STATE_WORD1:
|
||
|
begin
|
||
|
if (data_in_valid && data_out_ready_for3header)
|
||
|
begin
|
||
|
state <= STATE_WORD2;
|
||
|
tx_ctr <= tx_ctr +1'b1;
|
||
|
end
|
||
|
end
|
||
|
STATE_WORD2:
|
||
|
begin
|
||
|
if (data_in_valid && data_out_ready_for3header)
|
||
|
begin
|
||
|
state <= STATE_DATA_PRO;
|
||
|
tx_ctr <= tx_ctr +1'b1;
|
||
|
delay_ctr <= DELAY_CLOCKS -1'b1;
|
||
|
end
|
||
|
end
|
||
|
STATE_DATA_PRO:
|
||
|
begin
|
||
|
if (data_in_valid)
|
||
|
begin
|
||
|
delay_ctr <= delay_ctr -1'b1;
|
||
|
if (delay_ctr == 0)
|
||
|
begin
|
||
|
state <= STATE_DATA_NEXT;
|
||
|
delay_ctr <= DELAY_CLOCKS - 1'b1;
|
||
|
signal0_17bit <= {1'b0, data_in_data[31:16]}-{1'b0,bkgH};
|
||
|
signal1_17bit <= {1'b0, data_in_data[15:0]}-{1'b0,bkgL};
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
STATE_DATA_NEXT:
|
||
|
begin
|
||
|
if (data_out_ready)
|
||
|
begin
|
||
|
tx_ctr <= tx_ctr+1'b1;
|
||
|
if (tx_ctr == WORDS_TO_SEND -1) //last word, size matches
|
||
|
state <= STATE_LOC;
|
||
|
else
|
||
|
state <= STATE_DATA_PRO;
|
||
|
end
|
||
|
end
|
||
|
STATE_LOC:
|
||
|
begin
|
||
|
state <= STATE_IDLE;
|
||
|
end
|
||
|
default:
|
||
|
begin
|
||
|
state <= STATE_IDLE;
|
||
|
end
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
|
||
|
//output 163 words
|
||
|
//assign data_in_ready = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2 || state == STATE_DATA_NEXT)&&data_out_ready;
|
||
|
//assign data_out_valid = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2 || state == STATE_DATA_NEXT) ? 1'b1 : 1'b0;
|
||
|
//the output data is be reversed....so during transfer without signal it's FFFFF, the software HIT-DAQ will reverse it again
|
||
|
//assign data_out_data = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2)? data_in_data:
|
||
|
// (state == STATE_DATA_NEXT)? {signal0,signal1}: 0;
|
||
|
//assign data_out_startofpacket = data_in_startofpacket;
|
||
|
//assign data_out_endofpacket = (state == STATE_DATA_NEXT & tx_ctr == WORDS_TO_SEND-1) ? 1'b1 : 1'b0;
|
||
|
//assign data_out_empty = 0;
|
||
|
|
||
|
//output 160 words
|
||
|
assign data_in_ready = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2) || (state == STATE_DATA_NEXT && data_out_ready);
|
||
|
assign data_out_valid = (state == STATE_DATA_NEXT) ? 1'b1 : 1'b0;
|
||
|
assign data_out_data = (state == STATE_DATA_NEXT)? {signal0,signal1}: 0;
|
||
|
assign data_out_startofpacket = (state == STATE_DATA_NEXT && tx_ctr == 8'd3)? 1'b1: 1'b0;
|
||
|
assign data_out_endofpacket = (state == STATE_DATA_NEXT & tx_ctr == WORDS_TO_SEND-1) ? 1'b1 : 1'b0;
|
||
|
assign data_out_empty = 0;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
endmodule
|