記述例 - シリアル受信回路
RTL記述の感じをつかんでもらうために記述例をあげる。
■機能
シリアルデータ(クロック同期,8ビット固定長)をシフトレジスタで受信して、パラレルデータとして出力する。
全系はクロック(clk,100MHz)のみで動作させるため、遅いシリアルクロック(s_clk,10MHz)はサンプリングして立ち上がりエッジのパルス(s_clk_rise)を作り、このタイミングでシリアルイネーブルとデータをサンプリングする。
■ブロック図
■タイミングチャート
■Verilogによる記述例
/* serrcv.v - serial receive */ module serrcv (input rst // リセット ,input s_clk // シリアルクロック ,input s_enb // シリアルイネーブル ,input s_dat // シリアルデータ ,input clk // クロック ,output[7:0] p_dat // パラレルデータ ); reg [2:0] s_clk_reg; // s_clkのエッジ検出用シフトレジスタ wire s_clk_rise; // s_clkの立ち上がりエッジ reg s_enb_reg; // s_enb入力レジスタ reg [2:0] cnt_reg; // s_enb長カウンタ reg [7:0] rcv_reg; // s_datのシフトレジスタ reg [7:0] p_dat_reg; // p_dat出力レジスタ
/* s_clkのエッジを検出する */ always @(posedge clk or posedge rst) begin if(rst) s_clk_reg[2:0] <= 3'd0; else s_clk_reg[2:0] <= {s_clk_reg[1:0],s_clk}; end assign s_clk_rise = (s_clk_reg[2:1]==2'b01);
/* s_enbをラッチする */ always @(posedge clk or posedge rst) begin if(rst) s_enb_reg <= 1'b0; else if(s_clk_rise) s_enb_reg <= s_enb; end
/* s_datをシリアルパラレル変換する */ always @(posedge clk or posedge rst) begin if(rst) rcv_reg[7:0] <= 8'd0; else if(s_clk_rise) rcv_reg[7:0] <= {rcv_reg[6:0],s_dat}; end
/* s_enbの長さをカウントする*/ always @(posedge clk or posedge rst) begin if(rst) cnt_reg <= 3'd0; else if(s_clk_rise) cnt_reg <= (s_enb_reg)? (cnt_reg + 1'b1):3'd0; end
/* 8ビット入力したらパラレルレジスタに入れる */ always @(posedge clk or posedge rst) begin if(rst) p_dat_reg <= 3'd0; else if(s_clk_rise & (cnt_reg==3'd7)) p_dat_reg <= rcv_reg; end
endmodule |