一路PN码串行捕获设计--基于《通信收发信机的verilog实现与仿真》实例
這篇日子是參考《通信收發機的Verilog實現與仿真》第五章 Verilog在擴頻通信中的應用。
網路上有關PN碼產生以及捕獲資料很多,但是介于本人對其原理的模糊,實在不知道設計時每一步的具體操作如何。所以花點時間學習一下,放在這里,以防忘記。如果以后做移動通信,或許用的到。就這個東西,前前后后斷斷續續看了一個星期,花了時間,也算學習了東西。
?
譬如《通信收發信機的verilog實現與仿真》中就有PN碼的捕獲方案,該方案簡單介紹了PN碼的產生和捕獲原理。產生就是普通的M序列的方法,而捕獲用的是滑動相關法。為了加快捕獲的速度,設計中使用了10路相關信號,如果而10路相關信號每一路都占用單獨的邏輯,那么整個系統的邏輯占有量將成倍增長,原因是在滑動相關捕獲方案中首先需要相加,然后相乘。eg,一路捕獲,輸入是8bit,那么加法器就是兩輸入的8bit,乘法器就是兩輸入的16bit。十路捕獲,資源占有量,不可容忍,共20個8比特兩輸入加法器,20個16比特兩輸入乘法器。為了解決這個問題,本書以及眾多解決方案給出的方法是共享邏輯(書中說的是流水線),用三路加法器,二路乘法器來實現相關計算以及最后的檢測。因為接收到的信號包含同相信號和正交信號,所以實際上一共是6個加法器,四個乘法器。大大減少了資源。十路PN信號使用十個pn_generator例化實現,共享邏輯的核心和按照設計了一個計數器sys_counter,不同的時間對來自不同路的信號做對應的操作。我整理了一下,用verilogHDL語言的形式與自然語言聯合表示如下,不求語法正確,只求理解具體操作。
case(sys_counter)
4‘b0000:3、4、5路輸入的信號輸入到加法器輸入端,加法器進行0、1、2路相關運算;
4’b0001:6、7、8路輸入的信號輸入到加法器,加法器進行3、4、5路相關運算,0、1、2路的相關結果輸入到對應的相關結果寄存器;
4‘b0010:9路輸入的信號輸入到加法器,加法器進行6、7、8路相關運算,3、4、5路的相關結果輸入到對應的相關結果寄存器,0、1路相關結果輸入到乘法器輸入端;
4’b0011:加法器進行9路信號相關、6、7、8路的相關結果輸入到對應的相關結果寄存器,0、1路同相、正交信號功率存儲;2、3路相關結果輸入到乘法器輸入端;
4‘b0100:9路的相關結果輸入到對應的相關結果寄存器,4、5路相關結果到乘法器輸入端,2、3路同相、正交信號功率存儲;0、1路正交、同相相加存儲;
4’b0101:6、7路相關結果到乘法器輸入端,4、5路同相、正交信號功率存儲,2、4路正交、同相相加存儲,比較0路功率與閾值的大小,得到capture;
4‘b0110:8、9路相關結果輸入到乘法器,6、7路同相、正交信號功率存儲,4、5路正交、同相相加存儲,比較1路功率與閾值的大小,得到capture;
4’b0111:8、9路同相、正交信號功率存儲,6、7路正交、同相相加存儲,比較2路功率與閾值的大小,得到capture;
4‘b1000:8、9路正交、同相相加存儲,比較3路功率與閾值的大小,得到capture;
4’b1001:比較4路功率與閾值的大小,得到capture;
4‘b1010:比較5路功率與閾值的大小,得到capture;
4’b1011:比較6路功率與閾值的大小,得到capture;
4‘b1100:比較7路功率與閾值的大小,得到capture;
4’b1101:比較8路功率與閾值的大小,得到capture;
4‘b1110:比較9路功率與閾值的大小,得到capture;
4’b1111:0、1、2路輸入的信號輸入到加法器;
endcase
到4‘b1111,完成一個周期,因為每16個clk只需要度每一路完成一次操作,所以共享邏輯可以完成這樣的功能,而且分幾次寄存了計算的結果。數據的輸入速度是clk的1/16。
信號處理過程中分幾次寄存數據,輸入數據寄存,加法結果寄存(這個是必要的,也就是相關處理的結果寄存),乘法輸入寄存(需要提前將進行乘法的數據從相關結果寄存器中讀出)、乘法結果寄存、功率結果寄存。
計算步驟:輸入信號和加法器上次結果輸入到加法器根據PN值相加進行相關操作、求同相正交信號的平方、求一路信號的功率(也就是同相信號平方+正交信號平方)、閾值比較等到捕獲同步的結果。這寫代碼可以見參考書,有一次證明,看代碼是件痛苦的事情,這些代碼還有很多注釋。另外:可能作者最初寫代碼的時候是整個系統用一個module實現的,而為了排版書籍的緣故將原來的程序劃分為幾個塊,也為了更好的注釋,但是劃分塊以后沒有對一些信號進行更好的處理,譬如一些信號在一個塊中沒有定義卻拿來使用,而sys_counter在serial_xiangguan模塊中只是定義,沒有具體實現,讀者只有參考了后面的模塊才能知道。還有許多,不一一提及。而這個計數器為什么定義那么多位,而且為什么那樣定義,我還不清楚,等做完后續實驗再說一下。而且為了節省資源,對resi_*和resq_*進行了共享,先放置相關結果,等相關數據使用完畢后,再放置相關后平方的結果。等等,這些內容在程序中并沒有交代清楚。
?
對于上面的實例無法透徹理解的前提下,就覺得做一路捕獲試試,或許能夠理解基本原理與操作。不考慮系統的效率問題,單路信號,時鐘clk2設置為輸入數據的4倍就可以,基本操作還是相加實現相關、相乘實現同相或正交功率計算、相加得到信號功率、與閾值比較的到capture結果。pn_generator沒有變化。實現捕獲的程序如下。
module pn_capture(clk, clr, en, data_i, data_q, a, capture);
??? input clk;//4倍于 data的時鐘
??? input clr;//清除
??? input en;//使能
??? input [7:0] data_i;//同相信號
??? input [7:0] data_q;//正交信號
??? output reg capture;//捕獲信號
??
? input [6:0] a;//PN碼生成器初始值
? reg [1:0] count;//2bit計數器,控制計算過程
? parameter idle=2'b00,co_add=2'b01,mul=2'b10,power_add=2'b11;
????????????????????????????????????????? //對應不同的計算狀態
? parameter criterion=37'h07_ffff_ffff;//峰值閾值
? reg signed [14:0] resi_add;//同相相加結果,也就是相關
? reg signed [14:0] resq_add;//正交相加結果,也就是相關
? reg signed [35:0] mul_result_i;//同相相關后平方
? reg signed [35:0] mul_result_q;//正交相關后平方
? reg [36:0] res;//功率寄存
? wire pn;//PN碼
//生成PN碼??
pn_generator pn0(.a(a), .clk(clk),?.clr(clr),?.en(en),?.pn(pn));
?
//控制計算的計數器
always @(posedge?clk)
begin
??? if(clr)??? count<=0;
??? else??? if(en)????
????? begin
??????? if(count==2'b11)??? count<=0;
??????? else??? count<=count+1'b1;
??? end
??? else??? count<=0;
end
?
//
always @(posedge clk)
begin
??? if(clr)????
????? begin?
??????? resi_add<=0;resq_add<=0;
??????? mul_result_i<=0;mul_result_q<=0;
??????? res<=0;
??? end
? else??? if(en)
??????? case(count)
?????? idle:??? begin?
????????????????????? resi_add<=resi_add;resq_add<=resq_add;//
???????????????? end
????? ?co_add:? begin//相關
???????????????? if(pn)???
?????????????? ???? begin resi_add<=resi_add-data_i;
?????????????????????????????resq_add<=resq_add-data_q;end
??????????????? ?else??? begin resi_add<=resi_add+data_i;
????????????????????????? resq_add<=resq_add+data_q;end
???????????? end
???????? mul:???? begin?//相乘
??????????????????? mul_result_i[35:0]<=resi_add*resi_add;
???????????????? ?? mul_result_q[35:0]<=resq_add*resq_add;
??????????????????? ?end
??? power_add:??? begin res[36:0]<=mul_result_i+mul_result_q;end//功率
??? endcase
end
?
//捕獲判斷
always @(posedge clk)
begin
??? if(clr)??? capture<=0;
? else??? if(en)
????? begin
??????? if(res>criterion)??? capture<=1;
??????? else??? capture<=0;
??? end
??????? else??? capture<=0;
end
endmodule
?
?
按照作者的意圖,按照我的理解,將作者原來的程序修正如下。感受啊!作者不認真,真的要人命,作者一偷懶,讀者費死勁,作者一疏忽,讀者真是服。
module pn_serial_corelated(clk, clr, data_i, data_q, pn);
??? input clk;
??? input clr;
??? input [7:0] data_i;
??? input [7:0] data_q;
??? output reg pn;
??? reg pn_1;
? reg pn_2;
? reg en;
??? reg [6:0] a,a0,a1,a2,a3,a4,a5;
? wire [9:0]pn_10;
? reg signed [7:0] reg_i,reg_q;
? reg signed [14:0] resi_add_0,resi_add_1,resi_add_2;
? reg signed [14:0] resq_add_0,resq_add_1,resq_add_2;
? reg signed [14:0] resi_in_0,resi_in_1,resi_in_2;
? reg signed [14:0] resq_in_0,resq_in_1,resq_in_2;
? reg signed [35:0] resi_0,resi_1,resi_2,resi_3,resi_4;
? reg signed [35:0] resi_5,resi_6,resi_7,resi_8,resi_9;
? reg signed [35:0] resq_0,resq_1,resq_2,resq_3,resq_4;
? reg signed [35:0] resq_5,resq_6,resq_7,resq_8,resq_9;
? reg signed [36:0] res_0,res_1,res_2,res_3,res_4,res_5;
? reg signed [36:0] res_6,res_7,res_8,res_9;
? reg [3:0] waitnum;
? reg [16:0] sys_counter;
? reg [3:0] pn_max_num;
? reg [36:0] criterion;
? reg capture;
? reg signed [36:0] max;
? wire signed [35:0] mul_result_i_0;
? wire signed [35:0] mul_result_q_0;
? wire signed [35:0] mul_result_i_1;
? wire signed [35:0] mul_result_q_1;??
? reg signed [14:0] mul_i_0;
? reg signed [14:0] mul_q_0;
? reg signed [14:0] mul_i_1;
? reg signed [14:0] mul_q_1;
??
? wire en_pn;?
??
??
pn_generator mypn0(.a(a0),.clk(clk),.pn(pn_10[0]),.en(en_pn),.clr(clr));
pn_generator mypn1(.a(a1),.clk(clk),.pn(pn_10[1]),.en(en_pn),.clr(clr));
pn_generator mypn2(.a(a2),.clk(clk),.pn(pn_10[2]),.en(en_pn),.clr(clr));
pn_generator mypn3(.a(a3),.clk(clk),.pn(pn_10[3]),.en(en_pn),.clr(clr));
pn_generator mypn4(.a(a4),.clk(clk),.pn(pn_10[4]),.en(en_pn),.clr(clr));
pn_generator mypn5(.a(a5),.clk(clk),.pn(pn_10[5]),.en(en_pn),.clr(clr));
pn_generator mypn6(.a(a),.clk(clk),.pn(pn_10[6]),.en(en_pn),.clr(clr));
pn_generator mypn7(.a(a),.clk(clk),.pn(pn_10[7]),.en(en_pn),.clr(clr));
pn_generator mypn8(.a(a),.clk(clk),.pn(pn_10[8]),.en(en_pn),.clr(clr));
pn_generator mypn9(.a(a),.clk(clk),.pn(pn_10[9]),.en(en_pn),.clr(clr));
//按照面積優化,會將mypn7/mypn8/mypn9優化。
//wire en_pn;
assign en_pn=((sys_counter==4'b0011)&&en);
always @(posedge clk)
begin
??? if(clr)
????? begin
??????? a<=7'b100_0000;a0<=7'b000_1000;
????a1<=7'b000_0001;a2<=7'b100_0001;
????a3<=7'b100_0100;a4<=7'b100_1001;
????a5<=7'b100_1100;
????reg_i<=0;reg_q<=0;???
??? end
??? else??? if(en)
????? begin
??????? if(sys_counter[3:0]==4'b1111)
??????? begin
????????? reg_i<=data_i; reg_q<=data_q;
????? end
??? end
end
always @(posedge clk)
begin
???? if(clr)
?????? begin
????? resi_add_0<=0;resi_add_1<=0;resi_add_2<=0;
????resq_add_0<=0;resq_add_1<=0;resq_add_2<=0;
????resi_in_0<=0;resi_in_1<=0;resi_in_2<=0;
????resq_in_0<=0;resq_in_1<=0;resq_in_2<=0;
????resi_0<=0;resi_1<=0;resi_2<=0;resi_3<=0;resi_4<=0;
????resi_5<=0;resi_6<=0;resi_7<=0;resi_8<=0;resi_9<=0;
????resq_0<=0;resq_1<=0;resq_2<=0;resq_3<=0;resq_4<=0;
????resq_5<=0;resq_6<=0;resq_7<=0;resq_8<=0;resq_9<=0;
????res_0<=0;res_1<=0;res_2<=0;res_3<=0;res_4<=0;
????res_5<=0;res_6<=0;res_7<=0;res_8<=0;res_9<=0;
???end
??? else??? if(en)
????? begin
????? case(pn)
??? 1'b0:
??????? begin
??????? resi_add_0<=resi_in_0+reg_i;
????? resq_add_0<=resq_in_0+reg_q;
????end
??? 1'b1:
??????? begin
??????? resi_add_0<=resi_in_0-reg_i;
????? resq_add_0<=resq_in_0-reg_q;
????end
??? endcase
????? case(pn_1)
??? 1'b0:
??????? begin
??????? resi_add_1<=resi_in_1+reg_i;
????? resq_add_1<=resq_in_1+reg_q;
????end
??? 1'b1:
??????? begin
??????? resi_add_1<=resi_in_1-reg_i;
????? resq_add_1<=resq_in_1-reg_q;
????end
??? endcase????
??? case(pn_2)
??? 1'b0:
??????? begin
??????? resi_add_2<=resi_in_2+reg_i;
????? resq_add_2<=resq_in_2+reg_q;
????end
??? 1'b1:
??????? begin
??????? resi_add_2<=resi_in_2-reg_i;
????? resq_add_2<=resq_in_2-reg_q;
????end
??? endcase
??? case(sys_counter[3:0])
??? 4'b0000:
??????? begin
??????? pn<=pn_10[3];
????? pn_1<=pn_10[4];
????? pn_2<=pn_10[5];
????? resi_in_0<=resi_3[14:0];
????? resi_in_0<=resq_3[14:0];
????? resi_in_1<=resi_4[14:0];
????? resq_in_1<=resq_4[14:0];
????? resi_in_2<=resi_5[14:0];
????? resq_in_2<=resq_5[14:0];
????end
??????? 4'b0001:
??????? begin
??????? pn<=pn_10[6];
????? pn_1<=pn_10[7];
????? pn_2<=pn_10[8];
????? resi_0[14:0]<=resi_add_0;
????? resi_1[14:0]<=resi_add_1;
????? resi_2[14:0]<=resi_add_2;
????? resi_in_0<=resi_6[14:0];
????? resi_in_1<=resi_7[14:0];
????? resi_in_2<=resi_8[14:0];
????? resq_0[14:0]<=resq_add_0;
????? resq_1[14:0]<=resq_add_1;
????? resq_2[14:0]<=resq_add_2;
????? resq_in_0<=resq_6[14:0];
????? resq_in_1<=resq_7[14:0];
????? resq_in_2<=resq_8[14:0];
????end
??? 4'b0010:
??????? begin
??????? pn<=pn_10[9];
????? resi_3[14:0]<=resi_add_0;
????? resi_4[14:0]<=resi_add_1;
????? resi_5[14:0]<=resi_add_2;
????? resi_in_0<=resi_9[14:0];
????? resq_3[14:0]<=resq_add_0;
????? resq_4[14:0]<=resq_add_1;
????? resq_5[14:0]<=resq_add_2;
????? resq_in_0<=resq_9[14:0];
??????
????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? mul_i_0<=resi_0[14:0];
????????mul_q_0<=resq_0[14:0];
????????mul_i_1<=resi_1[14:0];
????????mul_q_1<=resq_1[14:0];
??????? end
????end
??????? 4'b0011:
??????? begin
??????? resi_6[14:0]<=resi_add_0;
????? resi_7[14:0]<=resi_add_1;
????? resi_8[14:0]<=resi_add_2;
????? resq_6[14:0]<=resq_add_0;
????? resq_7[14:0]<=resq_add_1;
????? resq_8[14:0]<=resq_add_2;
????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? mul_i_0<=resi_2[14:0];
????????mul_q_0<=resq_2[14:0];
????????mul_i_1<=resi_3[14:0];
????????mul_q_1<=resq_3[14:0];
????????resi_0<=mul_result_i_0;
????????resq_0<=mul_result_q_0;
????????resi_1<=mul_result_i_1;
????????resi_1<=mul_result_q_1;
??????? end
????end
??? 4'b0100:
??????? begin
??????? resi_9[14:0]<=resi_add_0;
????? resq_9[14:0]<=resq_add_0;
????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? mul_i_0<=resi_4[14:0];
????????mul_q_0<=resq_4[14:0];
????????mul_i_1<=resi_5[14:0];
????????mul_q_1<=resq_5[14:0];
????????resi_2<=mul_result_i_0;
????????resq_2<=mul_result_q_0;
????????resi_3<=mul_result_i_1;
????????resq_3<=mul_result_q_1;
????????res_0<=resi_0+resq_0;
????????res_1<=resi_1+resq_1;
??????? end
??????
????end
??? 4'b0101:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? mul_i_0<=resi_6[14:0];
????????mul_q_0<=resq_6[14:0];
????????mul_i_1<=resi_7[14:0];
????????mul_q_1<=resq_7[14:0];
????????resi_4<=mul_result_i_0;
????????resq_4<=mul_result_q_0;
????????resi_5<=mul_result_i_1;
????????resi_5<=mul_result_q_1;
????????res_2<=resi_2+resq_2;
????????res_3<=resi_3+resq_3;
????????if(res_0>max)
??????????? begin
????????????? pn_max_num<=0;
??????????? max<=res_0;
????????? end
??????? end
????end
??? 4'b0110:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
?????????? mul_i_0<=resi_8[14:0];
???????? mul_q_0<=resq_8[14:0];
???????? mul_i_1<=resi_9[14:0];
???????? mul_q_1<=resq_9[14:0];
???????? resi_6<=mul_result_i_0;
???????? resq_6<=mul_result_q_1;
???????? resi_7<=mul_result_i_1;
???????? resi_7<=mul_result_q_1;
???????? res_4<=resi_4+resq_4;
???????? res_5<=resi_5+resq_5;
???????? if(res_1>max)
???????????? begin
???????????? pn_max_num<=1;
?????????? max<=res_1;
?????????end
??????? end
????end
??? 4'b0111:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
??????????????????? begin
??????????? resi_8<=mul_result_i_0;
????????resq_8<=mul_result_q_0;
????????resi_9<=mul_result_i_1;
????????resq_9<=mul_result_q_1;
????????res_6<=resi_6+resq_6;
????????res_7<=resi_7+resq_7;
????????if(res_2>max)
??????????? begin
????????????? pn_max_num<=2;
??????????? max<=res_2;
????????? end
??????????????????? end????????
????end
??? 4'b1000:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? res_8<=resi_8+resq_8;
????????res_9<=resi_9+resq_9;
????????if(res_3>max)
??????????? begin
????????????? pn_max_num<=3;
??????????? max<=res_3;
????????? end
??????? end
????end
??? 4'b1001:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? if(res_4>max)
??????????? begin
????????????? pn_max_num<=4;
??????????? max<=res_4;
????????? end
??????? end
????end
??? 4'b1010:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? if(res_5>max)
??????????? begin
????????????? pn_max_num<=5;
??????????? max<=res_5;
????????? end
??????? end????????
????end
??? 4'b1011:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? if(res_6>max)
??????????? begin
????????????? pn_max_num<=6;
??????????? max<=res_6;
????????? end
??????? end?????????
????end
??? 4'b1100:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? if(res_7>max)
??????????? begin
????????????? pn_max_num<=7;
??????????? max<=res_7;
????????? end
??????? end?????????
????end
??????? 4'b1101:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? if(res_8>max)
??????????? begin
????????????? pn_max_num<=8;
??????????? max<=res_8;
????????? end
??????? end?????????
????end?
??????? 4'b1110:
??????? begin
??????? if(sys_counter[10:4]==7'b000_0000)
????????? begin
??????????? if(res_9>max)
??????????? begin
????????????? pn_max_num<=9;
??????????? if(res_9>criterion)??? capture<=1;
????????? end
??????????? else
??????????? begin
????????????? if(max>criterion)??? capture<=1;
????????? end
??????? end?????????
????end????
??? 4'b1111:
??????? begin
??????? pn<=pn_10[0];
????? pn_1<=pn_10[1];
????? pn_2<=pn_10[2];
????? resi_in_0<=resi_0[14:0];
????? resi_in_1<=resi_1[14:0];
????? resi_in_2<=resi_2[14:0];
????? resq_in_0<=resq_0[14:0];
????? resq_in_1<=resq_1[14:0];
????? resq_in_2<=resq_2[14:0];
????end
??? default:
??????? begin
????resi_in_0<=resi_in_0;resi_in_1<=resi_in_1;resi_in_2<=resi_in_2;
????resq_in_0<=resq_in_0;resq_in_1<=resq_in_1;resq_in_2<=resq_in_2;
????resi_0<=resi_0;resi_1<=resi_1;resi_2<=resi_2;resi_3<=resi_3;resi_4<=resi_4;
????resi_5<=resi_5;resi_6<=resi_6;resi_7<=resi_7;resi_8<=resi_8;resi_9<=resi_9;
????resq_0<=resq_0;resq_1<=resq_1;resq_2<=resq_2;resq_3<=resq_3;resq_4<=resq_4;
????resq_5<=resq_5;resq_6<=resq_6;resq_7<=resq_7;resq_8<=resq_8;resq_9<=resq_0;
??????????? end????
??? endcase
??? end
end
always @(posedge clk)
begin
??? if(clr)??? begin waitnum<=0;en<=1;end
? else??? if(~en)
????? begin
??????? waitnum<=waitnum+1'b1;
????if(waitnum==4'b1111)??? en<=1;
??? end
??? else??? if(sys_counter[10:0]==11'b000_0000_1111)
????? begin
??????? if(res_9<criterion&&max<criterion)??? en<=0;
??? end
end
always @(posedge clk)
begin
??? if(clr)??? sys_counter<=0;
? else??? if(en)
????? begin
??????? if(sys_counter[10:0]==11'b000_0000_1111)
//testbench里面這個地方是
//sys_counter[10:0]==11'b111_1110_1111;
??????? begin
????????? sys_counter[10:0]<=0;
??????? sys_counter[15:11]<=sys_counter[15:11]+1'b1;
????? end
????else??? sys_counter<=sys_counter+1'b1;
??? end
end
always @(posedge clk)
begin
??? if(clr)??? criterion<=37'h07_ffff_ffff;
end
MULT18X18 mult1(.P(mul_result_i_0),.A(mul_i_0),.B(mul_i_0));
MULT18X18 mult2(.P(mul_result_q_0),.A(mul_q_0),.B(mul_q_0));
MULT18X18 mult3(.P(mul_result_i_1),.A(mul_i_1),.B(mul_i_1));
MULT18X18 mult4(.P(mul_result_q_1),.A(mul_q_1),.B(mul_q_1));
??????
endmodule
作者沒有對每個模塊的測試平臺給出注釋,而且就其中用到的數據文本也沒給出基本的說明,希望再版的時候能注意一下。
下面是PN碼的一些知識,摘抄自《CDMA系統的PN碼技術》 武漢理工大學信息工程學院 吳薇
PN:Pseudo-Noise。
?
PN碼序列同步是擴頻系統特有的,也是擴頻技術?中的難點。CDMA系統要求接收機的本地偽隨機碼與接收到的PN碼在結構、頻率和相位上完全一致,否則就不能正常接收所發送的信息,接收到的只是一片噪聲。若實現了收發同步但不能保持同步,也無法準確可靠地獲取所發送的信息?數數據?。因此,PN碼序列的同步是CDMA擴頻通信的關鍵?技術?。?
CDMA系統中的PN碼同步過程分為PN碼捕獲(精同步)和PN碼跟蹤(細同步)兩部分。
?
常用的PN碼捕獲方法有:
1、滑動相關法
接收系統在搜索同步時,它的碼序列發生器以與發射機碼序列發生器不同的速率工作,致使這兩個碼序列在相位上互相滑動,只有在達到一致點時,才停下來,因此稱之為滑動相關法。
接收信號與本地PN碼相乘后積分,求出它們的互相關值,然后與門限檢測器的某一門限值比較,判斷是否已捕獲到有用信號。它利用了PN碼序列的相關徨性,當兩個相同的碼序列相位一致時,其相關值輸出最大。一旦確認捕獲完成,捕獲指示信號的同步脈沖控制搜索控制鐘,調整PN碼發生器產生的PN碼重復頻率和相位,使之與收到的信號保持同步。
由于滑動相關器對兩個PN碼序列按順序比較相關,所以該方法又稱順序搜索法。滑動相關器簡單,應用簋廣,缺點是當兩個PN碼的時間差或相位差過大時,相對滑動速度簋慢,導致搜索時間過長,特別是對長PN碼的捕獲時間過長,必須采取措施限定捕獲范圍,加快捕獲時間,改善其性能。
使滑動相關器實用的有效方法之一是采用特殊碼序列,特殊碼序列要足夠短,以便在合理時間內對所有碼位進行搜索。至于短到什么程度,由滿足相關性要求限定。這種加前置碼的方法稱同步引導法。引導碼同步要求低、簡單易實現,是適合各種應用的同步方法。
可捕碼由若干較短碼序列組合而成,其碼序列應與各組成碼序列保持一定的相關關系。這類碼中最著名的是JPL碼。
2、序貫估值法
序貫估值法是另一種減少長碼捕獲時間的快速捕獲方法,它把收到的PN碼序列直接輸入本地碼發生器的移位寄存器,強制改變各級寄存器的起始狀態,使其產生的PN碼與外來碼相位一致,系統即可立即進行同步跟蹤狀態,縮短了本地PN碼與外來PN碼相位一致所需的時間。
該方法先檢測收到碼信號中的PN碼,通過開關,送入n級PN碼發生器的移位寄存器。待整個碼序列全部進入填滿后,在相關器中,將產生的PN碼與收到的碼信號進行相關運算,在比較器中將所得結果與門限進行比較。若未超過門限,則繼續上述過程。若超過門限,則停止搜索,系統轉入跟蹤狀態。理想情況下,捕獲時間Ts=nTc,(Tc為PN碼片時間寬度)。該方法捕獲時間雖短,但存在一些問題,它先要對外來的PN碼進行檢測,才能送入移位寄存器,要做到這一點有時很困難。另外,此法抗干擾能力很差,因為逐一時片進行估值和判決,并未利用PN碼的抗干擾特性。但在無干擾條件下,它仍有良好的快速初始同步性能。
?
3、匹配濾波器法
用于PN同步捕獲的匹配濾波器一般采用延時線匹配濾波器,其目的是識別碼序列,它能在特殊結構中識別特殊序列,而且只識別該序列。假設一個輸入信號是7bit碼序列1110010雙相調制的信號,每當碼有1-0過渡時,反相信號進入延時線,直到第1bit在T7,第2bit在T6。當全部時延元件都填滿,而且信號調制碼與濾波器時延元件相位一致時,T2的信號相位與T5、T6、T7的相位相同,時延元件T1、T3、T4也具有相同的信號相位。把{T2、T5、T6、T7}與{T1、T3、T4}兩組分別相加,把{T1、T3、T4}之和倒相輸出,再將這兩個結果相加,包含在全部7個元件中的信號能量同相相加,整個輸出是未處理的7倍。根據該能量關系可以識別碼序列。
要增強產生的信號,可以靠附加更多的時延元件實現,在這種結構中得到的處理增益為Gp=10lgn(n是參加求和的時延元件數)。
在要求快速鎖定及使用長碼的CDMA擴頻通信中,宜采用SAW-TDL-MF作同步器。對于待定信號,匹配濾波器具有時間?自動?能力,無需PN碼時鐘同步與RF載波相位鎖定,既避免了?數據?信息比特以外的同步,又完成了擴頻信號的相關處理。引導碼進入程控編碼SAW-TDL-MF后,其輸出是噪聲基底上的底尖相關峰。在擴頻通信中,噪聲功率控制接收機的AGC,因而信號功率(即相關峰值)在起伏的噪聲環境中變化很大。門限計算器的功能根據包絡檢測輸出,確定動態門限電平,提供給同步檢測器,保證在低SNR時有可允許的同步誤差。動態門限電平取在主峰高度與最大旁峰之間時,噪聲引起的底同步誤差最小。當SAW-TDL檢波輸出包絡超過動態門限時,同步檢測器為接收機寬帶頻率合成器提供一個邏輯電平同步信號。
?
××××××××××××××××××××××××××××××××××××××
開始想學習3G,看了一些資料,發現講協議的太多,根本無法下手,不懂的幾乎是整體。然后覺得看移動通信可能好點,果然涉及到具體技術的內容,再仔細才發現擴頻通信應該算是現在比較主流的一種技術。
最佳通信系統=最佳發送機+最佳接收機。
一般地,認為:最佳發送就是擴頻發送,最佳接受就是相關接受。
擴頻技術是一種信息處理傳輸技術。擴頻技術是利用同域傳輸數據(信息)無關的碼對被傳輸信號擴展頻譜,使之占有遠遠超過被傳送信息所必需的最小帶寬。具有較強的抗干擾、抗衰落、抗多徑性能以及頻譜利用率高、多址通信。
擴頻信號具有以下三個特性:
1.擴頻信號是不可預測的偽隨機的寬帶信號;
2.擴頻信號帶寬遠大于欲傳輸數據(信息)帶寬;
3.接收機中必須有與寬帶載波同步的副本。
? 傳輸信息時所用信號帶寬遠大于傳輸些信息所需最小帶寬的一種信號處理技術。發射端展寬頻帶是用獨立于所傳數據的碼來實現,接收端用同步的相同碼解擴以恢復所傳數據。擴頻的基本方法有,直接序列(DS)、跳頻(FH)、跳時(TH)和線性調頻(Chirp)等4種,目前人們所熟知的新一代手機標準CDMA就是直接序列擴頻技術的一個應用。而跳頻、跳時等技術則主要應用于軍事領域,以避免己方通信信號被敵方截獲或者干擾。擴頻的主要特點為:抗干擾,抗多徑衰落,低截獲概率,碼分多址能力,高距離分辨率和精確定時特性等。
?
?《擴頻通信數字基帶信號處理算法及其VLSI實現》 張欣 第七章 擴頻碼序列的捕獲
該文獻對PN碼的理論闡述比較有條理。并且給出了幾種捕獲的方法和VLSI結構。
總結
以上是生活随笔為你收集整理的一路PN码串行捕获设计--基于《通信收发信机的verilog实现与仿真》实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 去除le-table表格的hover效果
- 下一篇: [Redux/Mobx] 在redux中