2017-11-22 21 views
0

私の背景はソフトウェアになっています。(システム)Verilogには新しかったので、シーザーシフターを実装することになっていました(文字をN文字でシフトし、 3だけシフトABCXYZはDEFABCになります)、私は私がソフトウェアの場合と同様に、コードの重複を減らすことができることを期待して、次のように書いた:範囲を包むためのVerilogモジュラス演算子

/* every variable except 'direction' has the type 'byte' */ 
    always_comb 
    begin 
    shifted_char = fresh_char; /* don't touch bytes that aren't letters */ 
    is_lower_case = "z" >= fresh_char && fresh_char >= "a"; 
    is_upper_case = "Z" >= fresh_char && fresh_char >= "A"; 
    if (is_lower_case || is_upper_case) 
     begin 
     unique if (is_lower_case) 
      alphabet_start = "a"; 
     else if (is_upper_case) 
      alphabet_start = "A"; 
     alphabet_position = fresh_char - alphabet_start; 
     if (direction == "f") /* direction is a module parameter: f for forwards results in a shifter, any other value results in an 'unshifter' */ 
      new_alphabet_position = (26 + (alphabet_position + shift_by)) % 26; 
     else 
      new_alphabet_position = (26 + (alphabet_position - shift_by)) % 26; 
     shifted_char = new_alphabet_position + alphabet_start; 
     end 
    end 

私の質問は、()、それは前方にシフトだと仮定している:「%について26 "の部分では、シンセサイザーがその時点で得られる可能な値の範囲が[26、26 + 25 + 25]([26、76])であると推論できるので、 (> 26と> 52)を区別するのではなく、すべての可能な256の異なる入力を扱うときスマートコール - (> 26、> 52、> 78などのケースを考えることになるでしょうか?それとも良い方法がありますか?私は逃げる...)]?

は、私はいつも次の操作を行うことができます:

new_alphabet_position = alphabet_position + shift_by; 
if (new_alphabet_position > 25) 
    new_alpahbet_position -= 26; 

/* Or, for the reverse shifter: */ 

new_alphabet_position = alphabet_position - shift_by; 
if (new_alphabet_position < 0) 
    new_alpahbet_position += 26; 

を...しかし、興味があったと(私はより多くの人が答えることができるようになります期待している)ことを尋ねるだけでなく、関連する1たかった:CAN通常の非2のカウンター(例えば、 カウント< =(count + 1)%6; )を使用するために使用されますか? VHDLシンセ・ツールは、少なくとも1つのVHDLシンセ・ツールがそれを意図したとおりに解釈するかのように、hgleamon1の応答になります。https://forums.xilinx.com/t5/Synthesis/Modulus-synthesizable-or-non-synthesizable/td-p/747493

+0

にも、ソフトウェアの観点から、これが最も効率的なプログラムではありません。ハードウェアに関しては、いくつかの全加算器と分周器(%)を合成するように要求しています。もし醜い結果を生み出すことができます。すべてのアルゴリズムを再考する必要があるようです。また、クロックと何らかの形で同期させる必要があります。 – Serge

+0

@Sergeソフトウェアではどのように非効率的ですか?ハードウェアに関しては、合成ツールが論理的に同等のものを見つけたり、除算器を合成したりしないでしょうか?加算器に関しては、それは私にとってやむを得ないことです。ではない? – PistoletPierre

+0

私はあなたがアスキー文字だけで作業しているので、特殊なアルファベットを使用して+/- 26の余分な演算、特にモジュロ演算子を取り除くなど、別のアプローチを見つけることができるかもしれません。ソフトウェアでは、パフォーマンスがあまり意味を持たないプログラムのための追加の指示を許可することができます。ハードウェアでは、パフォーマンス、電力、面積、コストなどに大きな影響を与える可能性のあるシリコン/ラッツの無駄使いを始めます... – Serge

答えて

1

特殊なマクロセルがないかぎり、特に純粋な組合せロジックとして行われる場合、比較的長い伝搬遅延を有する。

シンセサイザーに応じて、 'alphabet_start'、 'alphabet_position'、 'new_alphabet_position'という変数が推測されます。あなたがそれらを使った方法は、仲介されたロジックです。だから、あなたがこのブロックの外側でそれらを参照しておらず、シンセサイザがまともな最適化をしていれば、ラッチではありません。それらがラッチではないことを保証するために、ifステートメントの外でデフォルト値を与えなければなりません。

'direction'以外のすべての変数が 'byte'型であることを示しています。これは 'shift_by'が25より大きい値または-25より小さい値を持つことを意味します(デフォルトで 'byte'は符号付きの値です)。モジュラスを使用する前に、符号付きの値を使用して3つの値(26 + (alphabet_position + shift_by))を追加することにより、mod26が10ビットの符号付き値で評価されるようになります。これは、8ビット値で使用する場合よりも多くのロジックを使用します。シンセサイザーが最適化を行うかもしれない変化がありますが、それほど大きくないかもしれません。

'shift_by'が26未満で-26より大きい(符号なしの場合は0以上)ことを保証できる場合、 'alphabet_position'または 'new_alphabet_position'は必要ありません。単純に 'shift_by'を加算または減算し、範囲外の場合は計算します。レンジチェックの場合は、8'(shifted_char-26) >= alphabet_startの場合は最初にチェックします。この理由は、正の数を比較していることを確認するためです。 "z" +25は符号付き8ビット値が負の147です。 8'()を8ビットの符号なしの値としてキャストすると、0以外の中間の9th +ビットがトリムされます。調整が必要ない場合は、hifted_char < alphabet_startのように、負数にオーバーフローする可能性が既に処理されているかどうかを確認します。

'shift_by'が範囲内にあることを保証できない場合は、modで選択する必要はありません。幸いにも、これは8ビットの符号付きの値で、元の悪い場合よりも10ビットの符号付きの値より優れています。これは理想的ではありませんが、私が提供できる最高のものです。 'shift_by'のドライバに合法的な値を割り当てて、それにmodを追加するロジックを追加する方が最適です。

SystemVerilogを使用しているため、機能的には"Z" >= fresh_char && fresh_char >= "A"と同じfresh_char inside { ["A":"Z"] }を使用することを検討してください。 insideはキーワードが合成可能であることを意図していますが、一般的にサポートされているかわかりません。

次のコードを検討してください。これは、ほとんどの最適化ではないかもしれないが、それはより多くのあなたの元のコードよりも最適化されています

always_comb 
begin 
    shift_by_mod26 = shift_by % 26; // %26 is not need if guaranteed asb(value) < 26 
    alphabet_start = (fresh_char inside { ["A":"Z"] }) ? "A" : "a"; 
    if (fresh_char inside { ["A":"Z"], ["a":"z"] }) 
    begin 
    if (direction == "f") 
     shifted_char = fresh_char + shift_by_mod26; 
    else 
     shifted_char = fresh_char - shift_by_mod26; 

    // subtract 26 first in case shifted_char is >127 
    // bring back to a positive if signed (>127 unsigned is negative signed) 
    if (8'(shifted_char-26) >= alphabet_start) 
     shifted_char -= 26; 
    else if (shifted_char < alphabet_start) 
     shifted_char += 26; 
    end 
    else 
    begin 
    /* don't touch bytes that aren't letters */ 
    shifted_char = fresh_char; 
    end 
end 

注:「方向は」タイプ「のバイト」ではない場合、それは少なくとも7ビットでなければなりません(符号なし)ワイド以上(不可知論サイン)全ての試合「F」


クロスポスト、クロスポストのためanswerquestion

関連する問題