// (C) Tomonori Izumi , Aug. 2012. All rigts reserved. // いずみ研 valid/wait インターフェース サンプル回路 // マルチサイクル演算の例 // 受け取ったら2クロック計算して次に渡す // 入力と出力の1サイクルの無駄を削減 // わかりやすさ優先の実装 // 厳密にレジスタ出力を求められる場合は不可 // (iwait,ovalid 出力直前にロジックを置いているため) 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 [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=(state==STATE_RECEIVE)?0:1; assign ovalid=(state==STATE_TRANSMIT)?1:0; 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; odata_reg<=16'hffff; data<=16'hffff; end else begin case (state) STATE_RECEIVE: begin if (ivalid&!iwait) begin data<=idata; // データ受信 state<=STATE_CALC1; end end STATE_CALC1: begin data<=calc1(data); state<=STATE_CALC2; end STATE_CALC2: begin odata_reg<=calc2(data); // 送信データ state<=STATE_TRANSMIT; end STATE_TRANSMIT: begin if (ovalid&!owait) begin odata_reg<=16'hffff; // デバグ用(実際は不要) state<=STATE_RECEIVE; end end endcase end end endmodule // ifsmpl