// (C) Tomonori Izumi , Aug. 2012. All rigts reserved. // いずみ研 valid/wait インターフェース サンプル回路 // マルチサイクル演算の例 // 受け取ったら2クロック計算して次に渡す // 入力と出力の1サイクルの無駄を削減 // レジスタ出力(1サイクル前に代入) // 可読性が多少悪化し、回路量も少し増える module ifsmpl (xrst,clk, idata,ivalid,iwait, odata,ovalid,owait); input xrst,clk; input [15:0] idata; input ivalid; output iwait; output [15:0] odata; output ovalid; input owait; reg iwait_reg; reg ovalid_reg; reg [15:0] odata_reg; reg [1:0] state; parameter STATE_RECEIVE = 2'b00; parameter STATE_CALC1 = 2'b01; parameter STATE_CALC2 = 2'b10; parameter STATE_TRANSMIT = 2'b11; reg [15:0] data; assign iwait=iwait_reg; assign ovalid=ovalid_reg; assign odata=odata_reg; // 何らかの計算1 function [15:0] calc1; input [15:0] data; begin calc1=data; // 「何もしない」という計算 end endfunction // 何らかの計算2 function [15:0] calc2; input [15:0] data; begin calc2=data; // 「何もしない」という計算 end endfunction // メインステートマシン always @(posedge clk or negedge xrst) begin if (!xrst) begin state<=STATE_RECEIVE; iwait_reg<=0; ovalid_reg<=0; odata_reg<=16'hffff; data<=16'hffff; end else begin case (state) STATE_RECEIVE: begin if (ivalid&!iwait) begin data<=idata; // データ受信 iwait_reg<=1; // 次サイクルから受信不可 state<=STATE_CALC1; end end STATE_CALC1: begin data<=calc1(data); state<=STATE_CALC2; end STATE_CALC2: begin odata_reg<=calc2(data); // 送信データ ovalid_reg<=1; // 次サイクルに送信可 state<=STATE_TRANSMIT; end STATE_TRANSMIT: begin if (ovalid&!owait) begin odata_reg<=16'hffff; // デバグ用(実際は不要) ovalid_reg<=0; // 次サイクルから送信不可 iwait_reg<=0; // 次サイクルに受信可 state<=STATE_RECEIVE; end end endcase end end endmodule // ifsmpl