一路PN码串行捕获设计--基于《通信收发信机的verilog实现与仿真》实例
這篇日子是參考《通信收發(fā)機(jī)的Verilog實(shí)現(xiàn)與仿真》第五章 Verilog在擴(kuò)頻通信中的應(yīng)用。
網(wǎng)路上有關(guān)PN碼產(chǎn)生以及捕獲資料很多,但是介于本人對(duì)其原理的模糊,實(shí)在不知道設(shè)計(jì)時(shí)每一步的具體操作如何。所以花點(diǎn)時(shí)間學(xué)習(xí)一下,放在這里,以防忘記。如果以后做移動(dòng)通信,或許用的到。就這個(gè)東西,前前后后斷斷續(xù)續(xù)看了一個(gè)星期,花了時(shí)間,也算學(xué)習(xí)了東西。
?
譬如《通信收發(fā)信機(jī)的verilog實(shí)現(xiàn)與仿真》中就有PN碼的捕獲方案,該方案簡(jiǎn)單介紹了PN碼的產(chǎn)生和捕獲原理。產(chǎn)生就是普通的M序列的方法,而捕獲用的是滑動(dòng)相關(guān)法。為了加快捕獲的速度,設(shè)計(jì)中使用了10路相關(guān)信號(hào),如果而10路相關(guān)信號(hào)每一路都占用單獨(dú)的邏輯,那么整個(gè)系統(tǒng)的邏輯占有量將成倍增長(zhǎng),原因是在滑動(dòng)相關(guān)捕獲方案中首先需要相加,然后相乘。eg,一路捕獲,輸入是8bit,那么加法器就是兩輸入的8bit,乘法器就是兩輸入的16bit。十路捕獲,資源占有量,不可容忍,共20個(gè)8比特兩輸入加法器,20個(gè)16比特兩輸入乘法器。為了解決這個(gè)問題,本書以及眾多解決方案給出的方法是共享邏輯(書中說的是流水線),用三路加法器,二路乘法器來實(shí)現(xiàn)相關(guān)計(jì)算以及最后的檢測(cè)。因?yàn)榻邮盏降男盘?hào)包含同相信號(hào)和正交信號(hào),所以實(shí)際上一共是6個(gè)加法器,四個(gè)乘法器。大大減少了資源。十路PN信號(hào)使用十個(gè)pn_generator例化實(shí)現(xiàn),共享邏輯的核心和按照設(shè)計(jì)了一個(gè)計(jì)數(shù)器sys_counter,不同的時(shí)間對(duì)來自不同路的信號(hào)做對(duì)應(yīng)的操作。我整理了一下,用verilogHDL語言的形式與自然語言聯(lián)合表示如下,不求語法正確,只求理解具體操作。
case(sys_counter)
4‘b0000:3、4、5路輸入的信號(hào)輸入到加法器輸入端,加法器進(jìn)行0、1、2路相關(guān)運(yùn)算;
4’b0001:6、7、8路輸入的信號(hào)輸入到加法器,加法器進(jìn)行3、4、5路相關(guān)運(yùn)算,0、1、2路的相關(guān)結(jié)果輸入到對(duì)應(yīng)的相關(guān)結(jié)果寄存器;
4‘b0010:9路輸入的信號(hào)輸入到加法器,加法器進(jìn)行6、7、8路相關(guān)運(yùn)算,3、4、5路的相關(guān)結(jié)果輸入到對(duì)應(yīng)的相關(guān)結(jié)果寄存器,0、1路相關(guān)結(jié)果輸入到乘法器輸入端;
4’b0011:加法器進(jìn)行9路信號(hào)相關(guān)、6、7、8路的相關(guān)結(jié)果輸入到對(duì)應(yīng)的相關(guān)結(jié)果寄存器,0、1路同相、正交信號(hào)功率存儲(chǔ);2、3路相關(guān)結(jié)果輸入到乘法器輸入端;
4‘b0100:9路的相關(guān)結(jié)果輸入到對(duì)應(yīng)的相關(guān)結(jié)果寄存器,4、5路相關(guān)結(jié)果到乘法器輸入端,2、3路同相、正交信號(hào)功率存儲(chǔ);0、1路正交、同相相加存儲(chǔ);
4’b0101:6、7路相關(guān)結(jié)果到乘法器輸入端,4、5路同相、正交信號(hào)功率存儲(chǔ),2、4路正交、同相相加存儲(chǔ),比較0路功率與閾值的大小,得到capture;
4‘b0110:8、9路相關(guān)結(jié)果輸入到乘法器,6、7路同相、正交信號(hào)功率存儲(chǔ),4、5路正交、同相相加存儲(chǔ),比較1路功率與閾值的大小,得到capture;
4’b0111:8、9路同相、正交信號(hào)功率存儲(chǔ),6、7路正交、同相相加存儲(chǔ),比較2路功率與閾值的大小,得到capture;
4‘b1000:8、9路正交、同相相加存儲(chǔ),比較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路輸入的信號(hào)輸入到加法器;
endcase
到4‘b1111,完成一個(gè)周期,因?yàn)槊?6個(gè)clk只需要度每一路完成一次操作,所以共享邏輯可以完成這樣的功能,而且分幾次寄存了計(jì)算的結(jié)果。數(shù)據(jù)的輸入速度是clk的1/16。
信號(hào)處理過程中分幾次寄存數(shù)據(jù),輸入數(shù)據(jù)寄存,加法結(jié)果寄存(這個(gè)是必要的,也就是相關(guān)處理的結(jié)果寄存),乘法輸入寄存(需要提前將進(jìn)行乘法的數(shù)據(jù)從相關(guān)結(jié)果寄存器中讀出)、乘法結(jié)果寄存、功率結(jié)果寄存。
計(jì)算步驟:輸入信號(hào)和加法器上次結(jié)果輸入到加法器根據(jù)PN值相加進(jìn)行相關(guān)操作、求同相正交信號(hào)的平方、求一路信號(hào)的功率(也就是同相信號(hào)平方+正交信號(hào)平方)、閾值比較等到捕獲同步的結(jié)果。這寫代碼可以見參考書,有一次證明,看代碼是件痛苦的事情,這些代碼還有很多注釋。另外:可能作者最初寫代碼的時(shí)候是整個(gè)系統(tǒng)用一個(gè)module實(shí)現(xiàn)的,而為了排版書籍的緣故將原來的程序劃分為幾個(gè)塊,也為了更好的注釋,但是劃分塊以后沒有對(duì)一些信號(hào)進(jìn)行更好的處理,譬如一些信號(hào)在一個(gè)塊中沒有定義卻拿來使用,而sys_counter在serial_xiangguan模塊中只是定義,沒有具體實(shí)現(xiàn),讀者只有參考了后面的模塊才能知道。還有許多,不一一提及。而這個(gè)計(jì)數(shù)器為什么定義那么多位,而且為什么那樣定義,我還不清楚,等做完后續(xù)實(shí)驗(yàn)再說一下。而且為了節(jié)省資源,對(duì)resi_*和resq_*進(jìn)行了共享,先放置相關(guān)結(jié)果,等相關(guān)數(shù)據(jù)使用完畢后,再放置相關(guān)后平方的結(jié)果。等等,這些內(nèi)容在程序中并沒有交代清楚。
?
對(duì)于上面的實(shí)例無法透徹理解的前提下,就覺得做一路捕獲試試,或許能夠理解基本原理與操作。不考慮系統(tǒng)的效率問題,單路信號(hào),時(shí)鐘clk2設(shè)置為輸入數(shù)據(jù)的4倍就可以,基本操作還是相加實(shí)現(xiàn)相關(guān)、相乘實(shí)現(xiàn)同相或正交功率計(jì)算、相加得到信號(hào)功率、與閾值比較的到capture結(jié)果。pn_generator沒有變化。實(shí)現(xiàn)捕獲的程序如下。
module pn_capture(clk, clr, en, data_i, data_q, a, capture);
??? input clk;//4倍于 data的時(shí)鐘
??? input clr;//清除
??? input en;//使能
??? input [7:0] data_i;//同相信號(hào)
??? input [7:0] data_q;//正交信號(hào)
??? output reg capture;//捕獲信號(hào)
??
? input [6:0] a;//PN碼生成器初始值
? reg [1:0] count;//2bit計(jì)數(shù)器,控制計(jì)算過程
? parameter idle=2'b00,co_add=2'b01,mul=2'b10,power_add=2'b11;
????????????????????????????????????????? //對(duì)應(yīng)不同的計(jì)算狀態(tài)
? parameter criterion=37'h07_ffff_ffff;//峰值閾值
? reg signed [14:0] resi_add;//同相相加結(jié)果,也就是相關(guān)
? reg signed [14:0] resq_add;//正交相加結(jié)果,也就是相關(guān)
? reg signed [35:0] mul_result_i;//同相相關(guān)后平方
? reg signed [35:0] mul_result_q;//正交相關(guān)后平方
? reg [36:0] res;//功率寄存
? wire pn;//PN碼
//生成PN碼??
pn_generator pn0(.a(a), .clk(clk),?.clr(clr),?.en(en),?.pn(pn));
?
//控制計(jì)算的計(jì)數(shù)器
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//相關(guān)
???????????????? 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
?
?
按照作者的意圖,按照我的理解,將作者原來的程序修正如下。感受啊!作者不認(rèn)真,真的要人命,作者一偷懶,讀者費(fèi)死勁,作者一疏忽,讀者真是服。
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));
//按照面積優(yōu)化,會(huì)將mypn7/mypn8/mypn9優(yōu)化。
//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里面這個(gè)地方是
//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
作者沒有對(duì)每個(gè)模塊的測(cè)試平臺(tái)給出注釋,而且就其中用到的數(shù)據(jù)文本也沒給出基本的說明,希望再版的時(shí)候能注意一下。
下面是PN碼的一些知識(shí),摘抄自《CDMA系統(tǒng)的PN碼技術(shù)》 武漢理工大學(xué)信息工程學(xué)院 吳薇
PN:Pseudo-Noise。
?
PN碼序列同步是擴(kuò)頻系統(tǒng)特有的,也是擴(kuò)頻技術(shù)?中的難點(diǎn)。CDMA系統(tǒng)要求接收機(jī)的本地偽隨機(jī)碼與接收到的PN碼在結(jié)構(gòu)、頻率和相位上完全一致,否則就不能正常接收所發(fā)送的信息,接收到的只是一片噪聲。若實(shí)現(xiàn)了收發(fā)同步但不能保持同步,也無法準(zhǔn)確可靠地獲取所發(fā)送的信息?數(shù)數(shù)據(jù)?。因此,PN碼序列的同步是CDMA擴(kuò)頻通信的關(guān)鍵?技術(shù)?。?
CDMA系統(tǒng)中的PN碼同步過程分為PN碼捕獲(精同步)和PN碼跟蹤(細(xì)同步)兩部分。
?
常用的PN碼捕獲方法有:
1、滑動(dòng)相關(guān)法
接收系統(tǒng)在搜索同步時(shí),它的碼序列發(fā)生器以與發(fā)射機(jī)碼序列發(fā)生器不同的速率工作,致使這兩個(gè)碼序列在相位上互相滑動(dòng),只有在達(dá)到一致點(diǎn)時(shí),才停下來,因此稱之為滑動(dòng)相關(guān)法。
接收信號(hào)與本地PN碼相乘后積分,求出它們的互相關(guān)值,然后與門限檢測(cè)器的某一門限值比較,判斷是否已捕獲到有用信號(hào)。它利用了PN碼序列的相關(guān)徨性,當(dāng)兩個(gè)相同的碼序列相位一致時(shí),其相關(guān)值輸出最大。一旦確認(rèn)捕獲完成,捕獲指示信號(hào)的同步脈沖控制搜索控制鐘,調(diào)整PN碼發(fā)生器產(chǎn)生的PN碼重復(fù)頻率和相位,使之與收到的信號(hào)保持同步。
由于滑動(dòng)相關(guān)器對(duì)兩個(gè)PN碼序列按順序比較相關(guān),所以該方法又稱順序搜索法。滑動(dòng)相關(guān)器簡(jiǎn)單,應(yīng)用簋廣,缺點(diǎn)是當(dāng)兩個(gè)PN碼的時(shí)間差或相位差過大時(shí),相對(duì)滑動(dòng)速度簋慢,導(dǎo)致搜索時(shí)間過長(zhǎng),特別是對(duì)長(zhǎng)PN碼的捕獲時(shí)間過長(zhǎng),必須采取措施限定捕獲范圍,加快捕獲時(shí)間,改善其性能。
使滑動(dòng)相關(guān)器實(shí)用的有效方法之一是采用特殊碼序列,特殊碼序列要足夠短,以便在合理時(shí)間內(nèi)對(duì)所有碼位進(jìn)行搜索。至于短到什么程度,由滿足相關(guān)性要求限定。這種加前置碼的方法稱同步引導(dǎo)法。引導(dǎo)碼同步要求低、簡(jiǎn)單易實(shí)現(xiàn),是適合各種應(yīng)用的同步方法。
可捕碼由若干較短碼序列組合而成,其碼序列應(yīng)與各組成碼序列保持一定的相關(guān)關(guān)系。這類碼中最著名的是JPL碼。
2、序貫估值法
序貫估值法是另一種減少長(zhǎng)碼捕獲時(shí)間的快速捕獲方法,它把收到的PN碼序列直接輸入本地碼發(fā)生器的移位寄存器,強(qiáng)制改變各級(jí)寄存器的起始狀態(tài),使其產(chǎn)生的PN碼與外來碼相位一致,系統(tǒng)即可立即進(jìn)行同步跟蹤狀態(tài),縮短了本地PN碼與外來PN碼相位一致所需的時(shí)間。
該方法先檢測(cè)收到碼信號(hào)中的PN碼,通過開關(guān),送入n級(jí)PN碼發(fā)生器的移位寄存器。待整個(gè)碼序列全部進(jìn)入填滿后,在相關(guān)器中,將產(chǎn)生的PN碼與收到的碼信號(hào)進(jìn)行相關(guān)運(yùn)算,在比較器中將所得結(jié)果與門限進(jìn)行比較。若未超過門限,則繼續(xù)上述過程。若超過門限,則停止搜索,系統(tǒng)轉(zhuǎn)入跟蹤狀態(tài)。理想情況下,捕獲時(shí)間Ts=nTc,(Tc為PN碼片時(shí)間寬度)。該方法捕獲時(shí)間雖短,但存在一些問題,它先要對(duì)外來的PN碼進(jìn)行檢測(cè),才能送入移位寄存器,要做到這一點(diǎn)有時(shí)很困難。另外,此法抗干擾能力很差,因?yàn)橹鹨粫r(shí)片進(jìn)行估值和判決,并未利用PN碼的抗干擾特性。但在無干擾條件下,它仍有良好的快速初始同步性能。
?
3、匹配濾波器法
用于PN同步捕獲的匹配濾波器一般采用延時(shí)線匹配濾波器,其目的是識(shí)別碼序列,它能在特殊結(jié)構(gòu)中識(shí)別特殊序列,而且只識(shí)別該序列。假設(shè)一個(gè)輸入信號(hào)是7bit碼序列1110010雙相調(diào)制的信號(hào),每當(dāng)碼有1-0過渡時(shí),反相信號(hào)進(jìn)入延時(shí)線,直到第1bit在T7,第2bit在T6。當(dāng)全部時(shí)延元件都填滿,而且信號(hào)調(diào)制碼與濾波器時(shí)延元件相位一致時(shí),T2的信號(hào)相位與T5、T6、T7的相位相同,時(shí)延元件T1、T3、T4也具有相同的信號(hào)相位。把{T2、T5、T6、T7}與{T1、T3、T4}兩組分別相加,把{T1、T3、T4}之和倒相輸出,再將這兩個(gè)結(jié)果相加,包含在全部7個(gè)元件中的信號(hào)能量同相相加,整個(gè)輸出是未處理的7倍。根據(jù)該能量關(guān)系可以識(shí)別碼序列。
要增強(qiáng)產(chǎn)生的信號(hào),可以靠附加更多的時(shí)延元件實(shí)現(xiàn),在這種結(jié)構(gòu)中得到的處理增益為Gp=10lgn(n是參加求和的時(shí)延元件數(shù))。
在要求快速鎖定及使用長(zhǎng)碼的CDMA擴(kuò)頻通信中,宜采用SAW-TDL-MF作同步器。對(duì)于待定信號(hào),匹配濾波器具有時(shí)間?自動(dòng)?能力,無需PN碼時(shí)鐘同步與RF載波相位鎖定,既避免了?數(shù)據(jù)?信息比特以外的同步,又完成了擴(kuò)頻信號(hào)的相關(guān)處理。引導(dǎo)碼進(jìn)入程控編碼SAW-TDL-MF后,其輸出是噪聲基底上的底尖相關(guān)峰。在擴(kuò)頻通信中,噪聲功率控制接收機(jī)的AGC,因而信號(hào)功率(即相關(guān)峰值)在起伏的噪聲環(huán)境中變化很大。門限計(jì)算器的功能根據(jù)包絡(luò)檢測(cè)輸出,確定動(dòng)態(tài)門限電平,提供給同步檢測(cè)器,保證在低SNR時(shí)有可允許的同步誤差。動(dòng)態(tài)門限電平取在主峰高度與最大旁峰之間時(shí),噪聲引起的底同步誤差最小。當(dāng)SAW-TDL檢波輸出包絡(luò)超過動(dòng)態(tài)門限時(shí),同步檢測(cè)器為接收機(jī)寬帶頻率合成器提供一個(gè)邏輯電平同步信號(hào)。
?
××××××××××××××××××××××××××××××××××××××
開始想學(xué)習(xí)3G,看了一些資料,發(fā)現(xiàn)講協(xié)議的太多,根本無法下手,不懂的幾乎是整體。然后覺得看移動(dòng)通信可能好點(diǎn),果然涉及到具體技術(shù)的內(nèi)容,再仔細(xì)才發(fā)現(xiàn)擴(kuò)頻通信應(yīng)該算是現(xiàn)在比較主流的一種技術(shù)。
最佳通信系統(tǒng)=最佳發(fā)送機(jī)+最佳接收機(jī)。
一般地,認(rèn)為:最佳發(fā)送就是擴(kuò)頻發(fā)送,最佳接受就是相關(guān)接受。
擴(kuò)頻技術(shù)是一種信息處理傳輸技術(shù)。擴(kuò)頻技術(shù)是利用同域傳輸數(shù)據(jù)(信息)無關(guān)的碼對(duì)被傳輸信號(hào)擴(kuò)展頻譜,使之占有遠(yuǎn)遠(yuǎn)超過被傳送信息所必需的最小帶寬。具有較強(qiáng)的抗干擾、抗衰落、抗多徑性能以及頻譜利用率高、多址通信。
擴(kuò)頻信號(hào)具有以下三個(gè)特性:
1.擴(kuò)頻信號(hào)是不可預(yù)測(cè)的偽隨機(jī)的寬帶信號(hào);
2.擴(kuò)頻信號(hào)帶寬遠(yuǎn)大于欲傳輸數(shù)據(jù)(信息)帶寬;
3.接收機(jī)中必須有與寬帶載波同步的副本。
? 傳輸信息時(shí)所用信號(hào)帶寬遠(yuǎn)大于傳輸些信息所需最小帶寬的一種信號(hào)處理技術(shù)。發(fā)射端展寬頻帶是用獨(dú)立于所傳數(shù)據(jù)的碼來實(shí)現(xiàn),接收端用同步的相同碼解擴(kuò)以恢復(fù)所傳數(shù)據(jù)。擴(kuò)頻的基本方法有,直接序列(DS)、跳頻(FH)、跳時(shí)(TH)和線性調(diào)頻(Chirp)等4種,目前人們所熟知的新一代手機(jī)標(biāo)準(zhǔn)CDMA就是直接序列擴(kuò)頻技術(shù)的一個(gè)應(yīng)用。而跳頻、跳時(shí)等技術(shù)則主要應(yīng)用于軍事領(lǐng)域,以避免己方通信信號(hào)被敵方截獲或者干擾。擴(kuò)頻的主要特點(diǎn)為:抗干擾,抗多徑衰落,低截獲概率,碼分多址能力,高距離分辨率和精確定時(shí)特性等。
?
?《擴(kuò)頻通信數(shù)字基帶信號(hào)處理算法及其VLSI實(shí)現(xiàn)》 張欣 第七章 擴(kuò)頻碼序列的捕獲
該文獻(xiàn)對(duì)PN碼的理論闡述比較有條理。并且給出了幾種捕獲的方法和VLSI結(jié)構(gòu)。
總結(jié)
以上是生活随笔為你收集整理的一路PN码串行捕获设计--基于《通信收发信机的verilog实现与仿真》实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 去除le-table表格的hover效果
- 下一篇: PLSQL 之类型、变量和结构