openofdm02:Short Preamble Detection

 

Some repeating patterns can clearly be seen. We can utilize this characteristic and calculate the auto correlation metric of incoming signals to detect such pattern:

corr[i]=\frac { \begin{Vmatrix} \sum_{j=0}^{N} S[i+j] \times \overline{S[i+j+16]} \end{Vmatrix} } { \sum_{j=0}^{N} S[i+j] \times \overline{S[i+j]} }

where S[i] is the <I,Q> sample expressed as a complex number, and \overline{S[i]} is its conjugate, N is the correlation window size.

The correlation reaches 1 if the incoming signal is repeating itself every 16 samples. If the correlation stays high for certain number of continuous samples, then a short preamble can be declared.

The correlation value is almost 1 during the short preamble period, but drops quickly after that. We can also see that for the very first 20 samples or so, the correlation value is also very high. This is because the silence also repeats itself at arbitrary interval.

In current implementation, we use a fixed threshold(0.75) for the correlation so that we can use bit-shift to achieve the purpose. In particular, we calculate ( numerator>>1 + numerator>>2 ) and compare that with the denominator. For the correlation window size, we set N = 16.

In addition to the number of consecutive samples with correlation larger than 0.75, the sync_short module also checks if the incoming signal has both positive (>25%) and negative (>25%) samples to further eliminate false positive.

1. delay_sample

 DELAY_SHIFT = 4

//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//



module ram_2port
#(
    parameter DWIDTH=32,
    parameter AWIDTH=9
)
(
    input clka,
    input ena,
    input wea,
    input [AWIDTH-1:0] addra,
    input [DWIDTH-1:0] dia,
    output reg [DWIDTH-1:0] doa,

    input clkb,
    input enb,
    input web,
    input [AWIDTH-1:0] addrb,
    input [DWIDTH-1:0] dib,
    output reg [DWIDTH-1:0] dob
);

reg [DWIDTH-1:0] ram [(1<<AWIDTH)-1:0];
integer 	    i;
initial begin
    for(i=0;i<(1<<AWIDTH);i=i+1)
        ram[i] <= {DWIDTH{1'b0}};
    doa <= 0;
    dob <= 0;
end

always @(posedge clka) begin
    if (ena) 
    begin
        if (wea)
            ram[addra] <= dia;
        doa <= ram[addra];
    end
end
always @(posedge clkb) begin
    if (enb)
    begin
        if (web)
            ram[addrb] <= dib;
        dob <= ram[addrb];
    end
end
endmodule // ram_2port

ram_2port 模块

以端口A为例,ena有效,则输出ram[addra]至doa信号口。

ena有效且wea有效,则写入dia至ram地址addra中。

// delay_sample.v
/*
* Delay using RAM
* Only support 2^n delay
*/
module delay_sample
#(
    parameter DATA_WIDTH = 16,
    parameter DELAY_SHIFT = 4
)
(
    input clock, 
    input enable,
    input reset,

    input [(DATA_WIDTH-1):0] data_in,
    input input_strobe,

    output [(DATA_WIDTH-1):0] data_out,
    output reg output_strobe
);

localparam DELAY_SIZE = 1<<DELAY_SHIFT;

reg [DELAY_SHIFT-1:0] 	  addr;
reg full;

ram_2port  #(.DWIDTH(DATA_WIDTH), .AWIDTH(DELAY_SHIFT)) delay_line (
    .clka(clock),
    .ena(1),
    .wea(input_strobe),
    .addra(addr),
    .dia(data_in),
    .doa(),
    .clkb(clock),
    .enb(input_strobe),
    .web(1'b0),
    .addrb(addr),
    .dib(32'hFFFF),
    .dob(data_out)
);

always @(posedge clock) begin
    if (reset) begin
        addr <= 0;
        full <= 0;
    end else if (enable) begin
        if (input_strobe) begin
            addr <= addr + 1;
            if (addr == DELAY_SIZE-1) begin
                full <= 1;
            end
            output_strobe <= full;
        end else begin
            output_strobe <= 0;
        end
    end else begin
        output_strobe <= 0;
    end
end

endmodule

delay_sample模块

延迟DELAY_SIZE = 1<<DELAY_SHIFT个采样点

RAM的尺寸16bit*16,不断向RAM中存数据,一开始先不读数据,存满后开始读取数据,每次先读取数据再写入新的数据。

2. complex_to_mag_sq

 

module complex_to_mag_sq (
    input clock,
    input enable,
    input reset,

    input signed [15:0] i,
    input signed [15:0] q,
    input input_strobe,

    output [31:0] mag_sq,
    output mag_sq_strobe
);

reg valid_in;
reg [15:0] input_i;
reg [15:0] input_q;
reg [15:0] input_q_neg;

complex_mult mult_inst (
    .clock(clock),
    .reset(reset),
    .enable(enable),
    
    .a_i(input_i),
    .a_q(input_q),
    .b_i(input_i),
    .b_q(input_q_neg),
    .input_strobe(valid_in),

    .p_i(mag_sq),
    .output_strobe(mag_sq_strobe)
);

// <I, Q> => <I, -Q>
// delay 1 clock
always @(posedge clock) begin
    if (reset) begin
        input_i <= 0;
        input_q <= 0;
        input_q_neg <= 0;
        valid_in <= 0;
    end else if (enable) begin
        valid_in <= input_strobe;
        input_i <= i;
        input_q <= q;
        input_q_neg <= ~q+1;
    end
end
endmodule

module complex_mult
(
    input clock,
    input enable,
    input reset,

    input [15:0] a_i,
    input [15:0] a_q,
    input [15:0] b_i,
    input [15:0] b_q,
    input input_strobe,

    output reg [31:0] p_i,
    output reg [31:0] p_q,
    output output_strobe
);

localparam DELAY = 4;
reg [DELAY-1:0] delay;

reg [15:0] ar;
reg [15:0] ai;
reg [15:0] br;
reg [15:0] bi;

wire [31:0] prod_i;
wire [31:0] prod_q;

// ip 核
// delay 3 clock
complex_multiplier mult_inst (
    .clk(clock),
    .ar(ar),
    .ai(ai),
    .br(br),
    .bi(bi),
    .pr(prod_i),
    .pi(prod_q)
);

delayT #(.DATA_WIDTH(1), .DELAY(5)) stb_delay_inst (
    .clock(clock),
    .reset(reset),

    .data_in(input_strobe),
    .data_out(output_strobe)
);

// delay 1 clock
always @(posedge clock) begin
    if (reset) begin
        ar <= 0;
        ai <= 0;
        br <= 0;
        bi <= 0;
        p_i <= 0;
        p_q <= 0;
        delay <= 0;
    end else if (enable) begin
        ar <= a_i;
        ai <= a_q;
        br <= b_i;
        bi <= b_q;

        p_i <= prod_i;
        p_q <= prod_q;
    end
end

endmodule

 复数乘法器ip核 complex_multiplier

p_r+jp_i = \left( a_r + j a_i \right ) \cdot \left( b_r + j b_i \right )

p_r + j p_i 相比 \left( a_r + j a_i \right ) \cdot \left( b_r + j b_i \right ) 延时3个clock时间单元

module delayT
#(
    parameter DATA_WIDTH = 32,
    parameter DELAY = 1
)
(
    input clock,
    input reset,

    input [DATA_WIDTH-1:0] data_in,
    output [DATA_WIDTH-1:0] data_out
);

reg [DATA_WIDTH-1:0] ram[DELAY-1:0];
integer i;

assign data_out = ram[DELAY-1];

always @(posedge clock) begin
    if (reset) begin
        for (i = 0; i < DELAY; i = i+1) begin
            ram[i] <= 0;
        end
    end else begin
        ram[0] <= data_in;
        for (i = 1; i < DELAY; i= i+1) begin
            ram[i] <= ram[i-1];
        end
    end
end

endmodule

将输入数据data_in延时DELAY个clock周期,得到data_out

其中,数据位宽DATA_WIDTH和延时时间DELAY可设置。

3. complex_mult

 

4. moving_avg

module moving_avg
#(
    parameter DATA_WIDTH = 32,
    parameter WINDOW_SHIFT = 4,
    parameter SIGNED = 0
)
(
    input clock,
    input enable,
    input reset,

    input signed [DATA_WIDTH-1:0] data_in,
    input input_strobe,

    output reg signed [DATA_WIDTH-1:0] data_out,
    output reg output_strobe
);

localparam WINDOW_SIZE = 1<<WINDOW_SHIFT;
localparam SUM_WIDTH = DATA_WIDTH + WINDOW_SHIFT;

reg signed [(SUM_WIDTH-1):0] running_sum;

wire signed [DATA_WIDTH-1:0] old_data;
wire signed [DATA_WIDTH-1:0] new_data = data_in;

wire signed [SUM_WIDTH-1:0] ext_old_data = {{WINDOW_SHIFT{old_data[DATA_WIDTH-1]}}, old_data};
wire signed [SUM_WIDTH-1:0] ext_new_data = {{WINDOW_SHIFT{new_data[DATA_WIDTH-1]}}, new_data};


reg [WINDOW_SHIFT-1:0] addr;
reg full;

ram_2port  #(.DWIDTH(DATA_WIDTH), .AWIDTH(WINDOW_SHIFT)) delay_line (
    .clka(clock),
    .ena(1),
    .wea(input_strobe),
    .addra(addr),
    .dia(data_in),
    .doa(),
    .clkb(clock),
    .enb(input_strobe),
    .web(0),
    .addrb(addr),
    .dib(32'hFFFF),
    .dob(old_data)
);

integer i;
always @(posedge clock) begin
    if (reset) begin
        addr <= 0;
        running_sum <= 0;
        full <= 0;
        data_out <= 0;
    end else if (enable) begin
        if (input_strobe) begin
            addr <= addr + 1;
            data_out <= running_sum[SUM_WIDTH-1:WINDOW_SHIFT];

            if (addr == WINDOW_SIZE-1) begin
                full <= 1;
            end

            if (full) begin
                running_sum <= running_sum + ext_new_data- ext_old_data;
            end else begin
                running_sum <= running_sum + ext_new_data;
            end

            output_strobe <= full;
        end else begin
            output_strobe <= 0;
        end
    end else begin
        output_strobe <= 0;
    end
end
endmodule

有bug

17个数据 / 16

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值