作者bakerly (bakerly)
看板Electronics
標題Re: [問題] veriog撰寫問題
時間Thu Aug 6 14:20:45 2009
※ 引述《felghana (adol)》之銘言:
: module add_sub(clk,reset,mod_n,incr,decr);
: input clk,incr,decr,reset;
: output[12:0] mod_n;
: reg [1:0] state,next_state;
: reg [12:0] mod_n;
: parameter s0=2'd0,s1=2'd1,s2=2'd2,s3=2'd3;
: always@(posedge clk)
: begin
: if(reset)
: state=s0;
: else
: state=next_state;
: end
: //s0:重置用 s1:增加mod_n s2:減少mod_n s3:維持mod_n
: always@(state)
: begin
: case(state)
: s0:mod_n=13'd2000;
: s1:mod_n=mod_n+13'd10;
: s2:mod_n=mod_n-13'd10;
: default:;
: endcase
: end
這裡有三個問題
第一: 你少了s3的state, 在合成時state==s3時會發生什麼事沒人知道
第二: sensitive 少了mod_n, 這會造成latch。不過也許你是故意的
第三: 這種寫法會使你每次inc或dec多少次不一定
假設你一個clk 10nS
每次incr來會進s1這個state 10n
但是這個加法也許只花1n, 1nS後mod_n加完後的值又回到mod_n
10n可以作10次,如果你的加法花3n,那會作3次。我想這應該不是你要的
其實你要作的東西沒那麼復雜,下面有個例子你參考一下,應該就是你要的東西
: //當incr變為high時增加mod_n
: //當decr變為high時減少mod_n
: always@(state or incr or decr)
: begin
: case(state)
: s0:
: next_state=s3;
: s1:
: if(decr)
: next_state=s1;
: else
: next_state=s3;
: s2:
: if(incr)
: next_state=s2;
: else
: next_state=s3;
: s3:
: if(incr)
: next_state=s2;
: else if(decr)
: next_state=s1;
: else
: next_state=s3;
: default:
: next_state=s0;
: endcase
: end
: endmodule
: 上面是我寫的verilog 程式碼
: 目的是把mod_n傳到除頻器當除頻參數
: 所以藉由控制mod_n可以決定除頻後的頻率
: 我目前的問題是 使用quartus II燒錄至FPGA後
: 電路的動作完全錯誤 和我所撰寫的完全不同
: 想問版上的高手
: 我的code是不是有容易被合成軟體誤解的地方
: 我已經改了很多次還是一樣
: 麻煩好心的高手指點一下 謝謝
: 我把compile之後的warning訊息貼上來
: Warning: Found 1 node(s) in clock paths which may be acting as ripple and/or
: gated clocks -- node(s) analyzed as buffer(s) resulting in clock skew
: Warning: Circuit may not operate. Detected 23 non-operational path(s) clocked
: by clock "clk" with clock skew larger than data delay.
: ※ 編輯: felghana 來自: 58.114.132.207 (08/06 10:45)
前面的debounce省略
reg incr_d;
always @ ( posedge reset or posedge clk )
if ( reset ) incr_d <= 1'b0;
else incr_d <= incr;
wire incr_p = incr & ~incr_d;
reg decr_d;
always @ ( posedge reset or posedge clk )
if ( reset ) decr_d <= 1'b0;
else decr_d <= decr;
wire decr_p = decr & ~decr_d;
reg [12:0] mod_n;
always @ ( posedge reset or posedge clk )
if ( reset ) mod_n <= 13'h000;
else if ( incr_p ) mod_n <= mod_n + 13'h00a;
else if ( decr_p ) mod_n <= mod_n - 13'h00a;
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.124.168.118
推 felghana:我還是想問 如果incr變1 則incr_p變1 而且只維持到下一個 08/06 16:35
→ felghana:clk的正緣觸發 這樣的話 進去第三個always時 incr_p還是1 08/06 16:36
→ felghana:嗎? 這必須要先做完第三個always之後才把incr_p降為0耶 08/06 16:36
推 felghana:否則是無法讓mod_n+10的 08/06 16:39
→ bakerly:verilog的所有always都是一起發生的,所以沒有前後的問題 08/06 16:45
→ bakerly:前面的線路會產生一個1個clk寬的方波,不管你的incr來多久 08/06 16:46
→ bakerly:都不會產生第二個high, 這樣才能保證每次incr來都只加一次 08/06 16:48
推 felghana:我的意思是當你incr_p變為1之後的第一次posedge clk那一 08/06 19:50
→ felghana:瞬間 incr_p又會掉回0對吧 可是這時也會同時進去第三個 08/06 19:51
→ felghana:always 這樣能讓我的mod_n加10嗎? 08/06 19:53
→ felghana:除非他是先對incr_p做判斷之後 才讓incr_p=0 08/06 19:54
→ arclitetank:這麼多疑問 何不寫個 test bench 測一下呢? 08/06 21:13
推 tkhan:麻煩先畫電路出來再coding.. 08/06 21:16
推 luckyBF:真的覺得畫得出電路,才能把fpga學好~ 08/06 21:58
→ Uruzu:你在用C的觀念的寫RTL嗎? 08/06 22:38
推 TripleC:推樓上,我覺得是這樣 08/06 23:31
推 felghana:是嗎 我覺得就是因為三個always同時執行才會有我說的race 08/07 00:02
→ felghana:問題 如果用C來想 那那個程式根本完全錯 08/07 00:04
推 felghana:我現在只是懷疑他那樣會不會有race問題 而不是覺得一定錯 08/07 00:06
推 felghana:還有我第一次用fpga 所以不懂所謂畫出電路的意思是什麼? 08/07 00:28
→ Uruzu:我的意思是不要用程式語言的概念看待「硬體描述」語言 08/07 01:00