iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 16
0
自我挑戰組

Verilog 從放棄到有趣系列 第 16

[Day16]有限狀態機2/2

  • 分享至 

  • xImage
  •  

昨天介紹完 有限狀態機(Finite State Machine) 之後,今天來用一個電路實作給大家看,題目就是費伯納西數列(Fibonacci number),input output規格如下:

https://ithelp.ithome.com.tw/upload/images/20171227/20107543r44ovXh3H0.png

所以我們在寫電路之前先把架構想好,因為不是非常的複雜,所以就把FSM想好就好,那一個state該做什麼事情,那今天就用我的想法來實作.

https://ithelp.ithome.com.tw/upload/images/20171227/20107543NzKobm4dEc.png

沿用昨天畫的圖,就拿這個當我的FSM,再來是程式碼部分:

module Fibonacci (

input clk,
input reset,

input [7:0]in_level,
input in_valid,

output reg out_valid,
output reg [7:0]result

	);
	
parameter[1:0] IDLE = 0, CALCULATE = 1, COMPLETE = 2;

reg[1:0]Q, Q_NEXT;

reg[31:0]f1;
reg[31:0]f2;
reg [7:0]in_level_r;

wire done;
//FSM begin
always@(posedge clk)begin
  if(reset)
    Q <= IDLE;
  else
    Q <= Q_NEXT;
end

always@(*)begin
  case(Q)
    IDLE:
      if(in_valid) Q_NEXT = CALCULATE;
      else Q_NEXT = IDLE;
    CALCULATE:
      if(done) Q_NEXT = COMPLETE;
      else Q_NEXT = CALCULATE;
    COMPLETE:
      Q_NEXT = IDLE;
    default:
      Q_NEXT = IDLE;
  endcase
end
//FSM end
assign done = (in_level_r-1 == 0);

//signal controller
always@(posedge clk)begin
  case(Q)
    IDLE:
      in_level_r <= (in_valid) ? in_level : in_level_r;
    CALCULATE:
      in_level_r <= in_level_r-1;
    COMPLETE:
      in_level_r <= 0;
  endcase

end

always@(posedge clk)begin
  case(Q)
    IDLE:begin
      result <= 0;
      out_valid <= 0;
	 end
    CALCULATE:
      result <= f2;
    COMPLETE:
     out_valid <= 1;
  endcase
end

always@(posedge clk)begin
  case(Q)
    IDLE:begin
      f1 <= 1;
      f2 <= 1;
	  end
    CALCULATE:begin
      f1 <= f1 + f2;
      f2 <= f1;
	  end
  endcase
end


endmodule

為了增加可讀性,所以會幫每一個state取名字,所以會用parameter這個關鍵字宣告,上面程式可以看到說,每個變數都會依造不同的state去做不同的事情,所以我們只要控制好state,基本上電路就不會有太大的問題,那我來簡單介紹一下我寫的電路,一開始我會讓state停在IDLE等待input訊號,當要算的訊號進來之後我就跳到COMPUTE 這個state,接下來依照公式做累加,(大家都學過組合邏輯跟循序邏輯了,所以<=這符號應該知道怎麼用了,還不知道的可以往前面幾天複習),所以我會設一個done的flag,就是當我的level等於0時就代表算完了,那就可以跳到COMPLETE state去做輸出,因為輸出只要一個clock cycle,所以輸出完直接跳IDLE等待下一個input,那寫一個簡單的testbench給大家看:

for(i=0;i<10;i=i+1)begin
  in_valid = 1;
  in_level = ($random(seed) % 'd10) +1;
  $display("data level = %d\n",in_level);
  @(posedge clk);
  in_valid = 0;
  in_level = 0;          
  while(out_valid != 1)begin
  @(posedge clk);
  end
  $display("result = %d\n\n",result);
end
        
repeat(10)@(posedge clk);
$finish;

隨機產生10個random的input值,來看一段波形圖跟結果:

https://ithelp.ithome.com.tw/upload/images/20171227/20107543wMQ44rHiSY.png

大家可以看到當in_valid = 1時會給要算哪層level的值,接下來我有把Q這個FSM抓出來看,所已拿完input值後會開始運算,於是就跳到COMPUTE,算完到DONE且把out_valid設為1並輸出結果值,大家可以參考一下波形圖唷.

今天先到這邊,明天開始幾天會來分享一下verilog的coding style,有興趣的朋友們可以來看看喔.


上一篇
[Day15]有限狀態機1/2
下一篇
[Day17]Coding Style 1/2
系列文
Verilog 從放棄到有趣30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言