/* This is for get data from sensor(avalon_streaming source) And at the same time, frame counter counts the frameID bkg_sub do the bkg calibration and sub bkg depends on the frameID and cluster_locate start to locate the position of cluster when the bkg_sub_on is 1 at the mean time the data after bkg_sub is stored in ram4sig, as well as the first three words(I put it at address 500 to 502) */ `timescale 100 ps / 100 ps module algo_reconstruction ( //Clock/reset input wire clk_clk, // clk.clk input wire rst_reset, // connect to int_reset from sensor_interface, to reset frameID to 0; //avalon ST sink input logic unsigned[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 source output wire [31:0] data_out_data, // data_out.data output wire [1:0] data_out_empty, // .empty output wire data_out_endofpacket, // .endofpacket output wire data_out_startofpacket, // .startofpacket input wire data_out_ready, // .ready the UDP is ready output wire data_out_valid, // .valid output wire[26:0] frameID, // for assign signal in tb simulation output wire bkg_sub_on, output wire rst_frame, //data for sig after bkg subtraction input wire sig_rdclk, //the read port for sig_ram input wire[8:0] sig_rdaddress, //0~319 for data. 500~502 for the 3 words head output wire[31:0] sig_out, output reg sig_ram_last, //the output of cluster_locate output wire[8:0] sig_ch_left, output wire[8:0] sig_ch_right, output wire has_cluster, output wire no_cluster ); //set a frameID counter //frameID + 1 at the rising edge of data_in_startofpacket //wire[26:0] frameID; frame_counter framectr( .clk_clk(clk_clk), .rst_reset(rst_reset), .sig(data_in_startofpacket), .frame_Num(frameID) ); // *********************** 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 do calculation localparam STATE_DATA_NEXT = 5'd7; //sending data localparam STATE_LOC = 5'd5; //calculatebb //Helper stuff reg [15:0] tx_ctr; //counter of sent data words localparam WORDS_TO_SEND = 163; //the number of clocks for STATE_DATA_PRO reg [5:0] delay_ctr; localparam DELAY_CLOCKS = 3; // for sum reg[31:0] sum_all; //the bkg-ram wire[15:0] bkg_signal0; wire[15:0] bkg_signal1; wire[31:0] bkg_input_data; //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 bkg_but0( .clk_clk(clk_clk), .rst_reset(rst_reset), .frameID(frameID[26:0]), .address(tx_ctr[8:0]), .data_in_data(bkg_input_data[31:16]), .bkg_signal(bkg_signal0), .bkg_sub_status(bkg_sub_on) ); bkg_ram bkg_but1( .clk_clk(clk_clk), .rst_reset(rst_reset), .frameID(frameID[26:0]), .address(tx_ctr[8:0]), .data_in_data(bkg_input_data[15:0]), .bkg_signal(bkg_signal1) ); assign bkg_input_data = (state==STATE_DATA_NEXT)?~data_in_data:15'b0; //The state machine always @(posedge clk_clk or posedge rst_reset) begin if (rst_reset) 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_out_ready) begin state <= STATE_WORD1; tx_ctr <= tx_ctr+ 1'b1; end end STATE_WORD1: begin if (data_out_ready) begin state <= STATE_WORD2; tx_ctr <= tx_ctr +1'b1; end end STATE_WORD2: begin if (data_out_ready) begin state <= STATE_DATA_PRO; tx_ctr <= tx_ctr +1'b1; delay_ctr <= DELAY_CLOCKS -1; end end STATE_DATA_PRO: begin delay_ctr <= delay_ctr -1; if (delay_ctr == 0) begin state <= STATE_DATA_NEXT; delay_ctr <= DELAY_CLOCKS - 1; signal0_17bit <= {1'b0,~data_in_data[31:16]}-{1'b0,bkg_signal0}; signal1_17bit <= {1'b0,~data_in_data[15:0]}-{1'b0,bkg_signal1}; 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 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 : 0; //assign data_out_data = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2 || state == STATE_DATA_NEXT)? data_in_data: 0; 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 : 0; assign data_out_empty = 0; //the signal indicate the signal after bkg sub is ready or not wire sub_bkg_signal_ready; assign sub_bkg_signal_ready = (delay_ctr == 0)? 1 :0; //the rst signal for every frame //wire rst_frame; assign rst_frame = data_in_startofpacket || rst_reset; //the cluster_locating part //it is built by the fact that regardless data_out_ready signal, the STATE_DATA_PRO will go to STATE_DATA_NEXT //so the signal after bkg sub will continue at least two clocks reg[8:0] cl_address; wire[15:0] cl_data_in_data; wire cl_data_in_valid; // reg[8:0] ch_left; // reg[8:0] ch_right; // wire[8:0] sig_ch_left; // wire[8:0] sig_ch_right; // wire has_cluster; // wire no_cluster; cluster_locate cl_but( .clk_clk(clk_clk), .rst_reset(rst_frame), .address(cl_address), .data_in_data(cl_data_in_data), .data_in_valid(cl_data_in_valid), .sig_ch_left(sig_ch_left), .sig_ch_right(sig_ch_right), .has_cluster(has_cluster), .no_cluster(no_cluster) ); reg[2:0] state_clu; localparam STATE_CLU_IDLE = 0; localparam STATE_CLU_FIRST = 1; localparam STATE_CLU_SECOND = 3; assign cl_data_in_data = (state_clu == STATE_CLU_FIRST)? signal0: (state_clu == STATE_CLU_SECOND)? signal1: 0; assign cl_data_in_valid = (bkg_sub_on & (state_clu == STATE_CLU_FIRST || state_clu == STATE_CLU_SECOND))? 1'b1: 1'b0; always @ (posedge clk_clk or posedge rst_frame) begin if (rst_frame) begin state_clu <= STATE_CLU_IDLE; cl_address <= 9'b0; end else case(state_clu) STATE_CLU_IDLE: begin if (sub_bkg_signal_ready) state_clu <= STATE_CLU_FIRST; end STATE_CLU_FIRST: begin state_clu <= STATE_CLU_SECOND; cl_address <= cl_address + 1'b1; end STATE_CLU_SECOND: begin state_clu <= STATE_CLU_IDLE; cl_address <= cl_address + 1'b1; end default: state_clu <= STATE_CLU_IDLE; endcase end //when bkg_sub is not on, store the original data //store the signal after bkg_sub in ram //the first there words are at address 500~502 wire sig_ram_wren; wire[31:0] sig_ram_data; wire[8:0] sig_wraddress; ram4sig sig_ram ( .data(sig_ram_data), .rdaddress(sig_rdaddress), .rdclock(sig_rdclk), .wraddress(sig_wraddress), .wrclock(clk_clk), .wren(sig_ram_wren), .q(sig_out) ); assign sig_ram_wren = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2 || state_clu == STATE_CLU_FIRST || state_clu == STATE_CLU_SECOND)? 1: 0; assign sig_wraddress = (state == STATE_WORD0)? 9'd500: (state == STATE_WORD1)? 9'd501: (state == STATE_WORD2)? 9'd502: cl_address; assign sig_ram_data = (state == STATE_WORD0 || state == STATE_WORD1 || state == STATE_WORD2)? data_in_data: {16'b0,cl_data_in_data}; assign sig_ram_last = (state == STATE_LOC)? 1'b1: 1'b0; endmodule