重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

バレルシフタのVerilog記述について質問です。
画像のような仕様で左ローテーション回路をVerilogで作成しています。
実行結果が
0din=10000001 s=0 dout=10000001
1000din=10000001 s=1 dout=00000011
2000din=10000001 s=2 dout=00000110
3000din=10000001 s=3 dout=00001100
4000din=10000001 s=4 dout=00011000
5000din=10000001 s=5 dout=00110000
6000din=10000001 s=6 dout=01100000
7000din=10000001 s=7 dout=11000000
8000din=11111110 s=7 dout=11111111
となり、「8000din=11111110 s=7 dout=11111111」の部分を
「8000din=11111110 s=7 dout=01111111」にしたいです。
どうしたらなるのか分からなくて手詰まっています。
解説お願いします。
コード
module left_rotation(din,s,dout);
input [7:0] din;
input [2:0] s;
output [7:0] dout;
function [7:0] lrot;
input [7:0] din;
input [2:0] s;
case(s)
3'h0:lrot=din;
3'h1:lrot={1'b1,din[7]};
3'h2:lrot={1'b1,din[7:6]};
3'h3:lrot={1'b1,din[7:5]};
3'h4:lrot={1'b1,din[7:4]};
3'h5:lrot={1'b1,din[7:3]};
3'h6:lrot={1'b1,din[7:2]};
3'h7:lrot={1'b1,din[7:1]};
default:
lrot=8'bxxxxxxxx;
endcase
endfunction
assign dout=lrot(din,s);
endmodule
`timescale 1ps/1ps
module left_rotation_tp;
reg [7:0] din;
reg [2:0] s;
wire [7:0] dout;
parameter STEP=1000;
left_rotation left_rotation(din,s,dout);
initial begin
din=8'b10000001; s=3'h0;
#STEP s=3'h1;
#STEP s=3'h2;
#STEP s=3'h3;
#STEP s=3'h4;
#STEP s=3'h5;
#STEP s=3'h6;
#STEP s=3'h7;
#STEP din=8'b11111110; s=3'h7;
#STEP $finish;
end
initial $monitor($stime,"din=%b s=%h dout=%b",din,s,dout);
endmodule

「バレルシフタについて」の質問画像

A 回答 (1件)

3'h1:lrot={1'b1,din[7]};


これは2ビットのデータを8ビットの信号に入力しようとしているわけで、残りの6ビットはどうする? って話になります。
シミュレーションの結果が途中までうまくいっているのは、lrotがおそらくregタイプになるので、上位の値が決まらないビットが以前の値を保持しているためでしょう。
あと、lrotの最上位ビットが必ず1になるわけでもないので、{1'b1, ....}と決め打ちしているのもおかしい。

case文のなかを以下のようにすれば、

3'h0:lrot=din;
3'h1:lrot={din[6:0], din[7]};
3'h2:lrot={din[5:0],din[7:6]};
3'h3:lrot={din[4:0],din[7:5]};
3'h4:lrot={din[3:0],din[7:4]};
3'h5:lrot={din[2:0],din[7:3]};
3'h6:lrot={din[1:0],din[7:2]};
3'h7:lrot={din[0],din[7:1]};

シミュレーションの結果はこうなります。
0din=10000001 s=0 dout=10000001
1000din=10000001 s=1 dout=00000011
2000din=10000001 s=2 dout=00000110
3000din=10000001 s=3 dout=00001100
4000din=10000001 s=4 dout=00011000
5000din=10000001 s=5 dout=00110000
6000din=10000001 s=6 dout=01100000
7000din=10000001 s=7 dout=11000000
8000din=11111110 s=7 dout=01111111
$finish called from file "./test.v", line 53.
$finish at simulation time 9000


あと、functionやcaseを使わずにもっと簡単にやりたければ、シフト演算を使って、

module left_rotation(din,s,dout);
input [7:0] din;
input [2:0] s;
output [7:0] dout;

wire [15:0] temp;
assign temp = {8'b0, din[7:0]} << s;
assign dout = temp[7:0] | temp[15:8];

endmodule
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!