2022年11月26日土曜日

verilog : ビットシフト の記述

目的:

ビットシフトの記述の仕方について 記す

記述の仕方:

図のようなビットシフトを行う場合、次の様な記述の仕方がある。
  1. シフト演算子でシフト
    シフト演算子 ( << や >> ) を用いてシフトを行う。
  2. シフトした信号を定義してセレクト
    1bit づつシフトした信号を定義し、シフト量に応じて選択する。

通常は、シフト演算子でビットシフトを行う。
但し、下図の様に シフト量+元データ長 が シフト結果 のデータ長より長い場合、lintチェック等で Warning が 報告される。
はみ出した分は捨てられるのみで、合成は正常にできる為問題は無いが、Warning を減らしたい場合は 2. の記述をする。

また、下図の様に 元データ以外が '0' でない場合も 2. の記述で対応できる。


記述例:

シフトするデータを dat[2:0] (3bit), シフト結果を sft_data[7:0] (8bit),
シフト量を sft[3:0] (4bit) とし、左シフトする場合の記述例を示す。

  1. シフト演算子でシフト
    assign sft_data = dat << sft ;
  2. シフトした信号を定義してセレクト
    // シフトした信号の定義
    wire [7:0] sft_dt[0:8] ;
    assign sft_dt[0] = { 5'd0, dat } ;
    assign sft_dt[1] = { 4'd0, dat, 1'd0 } ;
    assign sft_dt[2] = { 3'd0, dat, 2'd0 } ;
    assign sft_dt[3] = { 2'd0, dat, 3'd0 } ;
    assign sft_dt[4] = { 1'd0, dat, 4'd0 } ;
    assign sft_dt[5] = { dat, 5'd0 } ;
    assign sft_dt[6] = { dat[1:0], 6'd0 } ;
    assign sft_dt[7] = { dat[0], 7'd0 } ;
    assign sft_dt[8] = 8'd0 ;
    // ビットシフト
    assign sft_data = (sft < 8) sft_dt[sft] : sft_dt[8] ;

各データ長をパラメータ化した場合の 2. の記述例を以下に示す。
 ( 1. の場合は パラメータ化しても 変わらない )

// パラメータ定義
parameter P_DT_BW    = 8 ;    // 元データ ビット幅
parameter P_SFTDT_BW = 128 ;  // シフト結果データ ビット幅
parameter P_SFT_BW   = 8 ;    // シフト量 ビット幅 (MAX 256)

// 各データの定義
wire [P_DT_BW-1:0]    dat ;      // 元データ
wire [P_SFTDT_BW-1:0] sft_data ; // シフト後のデータ
wire [P_SFT_BW-1:0]   sft ;      // シフト量

// シフトした信号の定義
wire  [P_SFTDT_BW-1:0]  sft_dt[0:P_SFTDT_BW]     ;
genvar i ;
generate
  for(i=0;i<P_SFTDT_BW-P_DT_BW;i=i+1) begin
    assign sft_dt[i] =
            {{(P_SFTDT_BW-P_DT_BW-i){1'b0}},dat,{(i){1'b0}}}  ;
  end
  for(i=0;i<P_DT_BW;i=i+1) begin
    assign sft_dt[P_SFTDT_BW-P_DT_BW+i] =
            {dat[P_DT_BW-i-1:0],{(P_SFTDT_BW-(P_DT_BW-i)){1'b0}}} ;
  end
  assign sft_dt[P_SFTDT_BW] = {(P_SFTDT_BW){1'b0}} ;
endgenerate
assign sft_data = (sft < P_SFTDT_BW) ? sft_dt[sft] :
                                       sft_dt[P_SFTDT_BW]  ;

元データ以外が base_data の場合 (パラメータ化)
// パラメータ定義
parameter P_DT_BW    = 8 ;    // 元データ ビット幅
parameter P_SFTDT_BW = 128 ;  // シフト結果データ ビット幅
parameter P_SFT_BW   = 8 ;    // シフト量 ビット幅 (MAX 256)

// 各データの定義
wire [P_DT_BW-1:0]    dat ;       // 元データ
wire [P_SFTDT_BW-1:0] sft_data ;  // シフト後のデータ
wire [P_SFTDT_BW-1:0] base_data ; // base_data
wire [P_SFT_BW-1:0]   sft ;       // シフト量

// シフトした信号の定義
wire  [P_SFTDT_BW-1:0]  sft_dt[0:P_SFTDT_BW]     ;
genvar i ;
generate
  assign sft_dt[0] = {base_data[P_SFTDT_BW-1:P_DT_BW], dat}  ;
  for(i=1;i<P_SFTDT_BW-P_DT_BW;i=i+1) begin
    assign sft_dt[i] =
             {base_data[P_SFTDT_BW1:P_DT_BW+i], dat, base_data[i-1:0]} ;
  end
  for(i=0;i<P_DT_BW;i=i+1) begin
    assign sft_dt[P_SFTDT_BW-P_DT_BW+i] =
             {dat[P_DT_BW-i-1:0], base_data[P_SFTDT_BW-P_DT_BW+i-1:0]} ;
  end
  assign sft_dt[P_SFTDT_BW] = base_data ;
endgenerate
assign sft_data = (sft < P_SFTDT_BW) ? sft_dt[sft] :
                                       sft_dt[P_SFTDT_BW]  ;

0 件のコメント:

コメントを投稿