2ask除錯模式比較簡單,就是用有訊號和沒有訊號來表示0,1。現在問題就是如何從基帶層面判斷乙個訊號是有還是沒有。當然是通過幅度。我們做乙個模組算出波谷的絕對值,和波峰相加就得到了幅度。之後設定兩個閾值,大於這個閾值1就認為是數值1,小於閾值0就認為是數值0,而在0,1之間的就保持之前的數值狀態。
module amp_cal(
input clk ,
input [11:0] adc_value ,
output reg [12:0] result,
output reg valid
);reg [11:0] trough,hill ,adc_value_r;
reg [11:0] abs_value ,abs_flag;
// stage 1
always @ (posedge clk )adc_value_r<=adc_value;
//stage 2
always @ (posedge clk) if (adc_value_r[11]) abs_value <= ~adc_value_r + 1 ; else abs_value <= adc_value_r ;
always @ (posedge clk) abs_flag <= adc_value_r[11] ;
//stage 3
reg abs_flagr ;
always @ (posedge clk) abs_flagr <= abs_flag ;wire fall_cross_zero = ==2'b01;
always @ (posedge clk)if (fall_cross_zero) trough<=0; else if (abs_flag) if (trough < abs_value) trough <= abs_value;
always @ (posedge clk)if (fall_cross_zero) hill<=0; else if (~abs_flag) if (hill < abs_value) hill <= abs_value;
//stage 4
always @(posedge clk) if (fall_cross_zero) result <= trough + hill ;
always @(posedge clk) valid <= fall_cross_zero;
endmodule
**按照流水線方式寫的,為了更好理解**,看下面這個圖:
波峰hill,波谷trough,從波峰降低到波谷穿越0點時候我們叫做fall_cross_zero。我fall_cross_zero時候我們看到hill和trough都已經算出來好了(都是正數,其中trough是波谷的絕對值),我們在fall_cross_zero是計算出來hill+trough就得到這這個週期的振幅。同時在fall_cross_zero時候清零波峰和波谷最大值儲存器。
這裡用流水線形式來寫出發點不是為了考慮速度,而是有些運算為了讓編譯器搞明白(或者說為了讓我們說明白,而不至於讓編譯器優化掉)多加暫存器的寫法還是很可取的。
這個應該沒有必要**的,想出錯都難。
我們這裡認為振幅超過一定的限度就是收到為了訊號。但是這裡存在乙個問題,如下圖表示:
在這例子裡面,始終沒有穿越0點,這樣也就時鐘算不出來乙個result 。所以這時候我們應該再加上乙個超時計數器,類似看門狗吧。當超過一定時間沒有valid產生,他就產生乙個復位訊號清除result 輸出0.這個超時的數值我們希望能可以設定,於是**可以這樣改寫:
/*
amp_cal_with_dog amp_cal_with_dog (
.clk( ),
.adc_value( ) ,
.result( ),
.valid( ) ,
.time_of_value( )
);*/
module amp_cal_with_dog (input clk ,
input [11:0] adc_value ,
output reg [12:0] result,
output reg valid ,
input [15:0]time_of_value
);wire [15:0] time_out_value_r ;
synchronizer #(.width ( 1 )) syn_time_of_value ( .clk(clk), .in(time_of_value), .out(time_of_value_r));
reg [15:0] cnt;
reg [11:0] trough,hill ,adc_value_r;
reg [11:0] abs_value ,abs_flag;
//stage 1
always @ (posedge clk )adc_value_r<=adc_value;
//stage 2
always @ (posedge clk) if (adc_value_r[11]) abs_value <= ~adc_value_r + 1 ; else abs_value <= adc_value_r ;
always @ (posedge clk) abs_flag <= adc_value_r[11] ;
//stage 3
reg abs_flagr ;
always @ (posedge clk) abs_flagr <= abs_flag ;wire fall_cross_zero = ==2'b01;
always @ (posedge clk)if (fall_cross_zero) trough<=0; else if (abs_flag) if (trough < abs_value) trough <= abs_value;
always @ (posedge clk)if (fall_cross_zero) hill<=0; else if (~abs_flag) if (hill < abs_value) hill <= abs_value;
//stage 4
wire cnt_overflow = cnt == time_of_value_r ;
always @(posedge clk) if (fall_cross_zero | cnt_overflow )cnt<=0;else cnt<=cnt+1;
always @(posedge clk) if ( cnt_overflow) result<=0;else if (fall_cross_zero) result <= trough + hill ;
always @(posedge clk) valid <= fall_cross_zero | cnt_overflow ;
endmodule
至於這個time_of_value如何設定呢,我認為設定1.5倍的週期就可以了。比方dds出乙個完整的波形用的點數是36,我們可以設定time_of_value為54 就可以。這裡注意of是overflow的簡寫。
ok這個模組寫好了,再繼續琢磨下要做什麼。
做乙個FSK的收發試驗 之一
這裡使用我們之前寫好的簡易的dds模組。我們先回顧一下用到的這個my dds模組。my dds my dds clk rst clr cnt step sin cos module my dds input clk rst,clr input 15 0 cnt,input 7 0 step outp...
做乙個programmer,而不做乙個coder
programmer是程式的思考者,而coder只是乙個執行者 勞心者製人,勞力者制於人 如果專案不緊的情況下,應該從需求做起,最好能夠窮盡所有的需求,遇到與別人模組互動的情況,規定好與別人互動的介面。然後才是開始設計,抓住需求當中的名詞,想想是否設計成為類,然後根據測試用例,來設計框架結構,至少要...
做乙個心靈富翁
你是否想過 怎樣的人生才是真的有價值?怎樣的生活才算自在而沒有遺憾?得到與失去 付出與收受 快樂與傷心 成功與失敗 我們又該如何看待其中的必然與不必然?親愛的,人生真的很複雜,複雜到我們窮其一生也難以解開奧秘 既然解不開,我們何妨單純看待呢!只要尋找一種屬於自己的簡單的幸福。簡單的幸福裡,也能有真實...