演習の前に,本演習のファイルを格納するディレクトリを作成する.
% cd % mkdir binshifttop
本演習で使用するファイルはすべて, binshifttop内に作成または,コピーする.
module binshiftreg(out,decimal,CLK,RST,CE); output [6:0] out; input [9:0] decimal; input CLK,RST,CE; // ↑ input, outputの定義はビット幅毎に endmodule
module binshiftreg(out,decimal,CLK,RST,CE); output [6:0] out; input [9:0] decimal; input CLK,RST,CE; wire [3:0] d; //← ビット幅が1以上の信号はwireで定義しておく. assign d=dectobin(decimal); //← function dectobinの出力をdに入力 function [3:0] dectobin; //← [3:0]は出力のビット幅を定義 input [9:0] in; //← function文の引数を定義 if(in[9]) //← functionの中には自由にif, caseが書ける dectobin = 9; else if(in[8]) dectobin = 8; else if(in[7]) dectobin = 7; //中略 else if(in[0]) dectobin = 0; //↑最後のelseがなくても組み合わせ回路になる endfunction endmodule
module binshiftreg(out,decimal,CLK,RST,CE); output [6:0] out; input [9:0] decimal; input CLK,RST,CE; wire [3:0] d; reg [1:0] count; reg [6:0] REGA; assign d=dectobin(decimal); function [3:0] dectobin; input [9:0] in; if(in[9]) dectobin = 9; else if(in[8]) dectobin = 8; else if(in[7]) dectobin = 7; else if(in[6]) dectobin = 6; else if(in[5]) dectobin = 5; else if(in[4]) dectobin = 4; else if(in[3]) dectobin = 3; else if(in[2]) dectobin = 2; else if(in[1]) dectobin = 1; else if(in[0]) dectobin = 0; endfunction always @(posedge CLK or negedge RST) begin if(!RST) begin REGA<=0; count<=0; end else if((decimal != 0) && (count < 2)) begin REGA<=(REGA*10)+d; count<=count+1; end else if(CE) begin REGA<=0; count<=0; end end assign out=REGA; endmodule
module syncro(out,in,CLK,RST); parameter WIDTH = 1; input [WIDTH-1:0] in; output [WIDTH-1:0] out; input CLK,RST; reg [ WIDTH-1:0] q0,q1,q2; always @(posedge CLK or negedge RST) begin if(!RST) q0<=0; else q0<=~in; end always @(posedge CLK or negedge RST) begin if(!RST) q1<=0; else q1<=q0; end always @(posedge CLK or negedge RST) begin if(!RST) q2<=0; else q2<=q1; end assign out=q1&(~q2); endmodule module binled(in,ledh,ledl); input [6:0] in; output [6:0] ledh,ledl; wire [3:0] outh,outl; bintobcd I0(.in(in),.outl(outl),.outh(outh)); ledout I1(.in(outl),.out(ledl)); ledout I2(.in(outh),.out(ledh)); endmodule module bintobcd(in,outl,outh); input [6:0] in; output [3:0] outl,outh; wire [6:0] tmp1,tmp2,tmp3; assign outh[3] = (in>=80) ? 1 : 0; assign tmp1 = (in>=80) ? in-80 : in; assign outh[2] = (tmp1>=40) ? 1 : 0; assign tmp2 = (tmp1>=40) ? tmp1-40 : tmp1; assign outh[1] = (tmp2>=20) ? 1 : 0; assign tmp3 = (tmp2>=20) ? tmp2-20 : tmp2; assign outh[0] = (tmp3>=10) ? 1 : 0; assign outl = (tmp3>=10) ? tmp3-10 : tmp3; endmodule `define SEG_OUT_0 7'b011_1111 `define SEG_OUT_1 7'b000_0110 `define SEG_OUT_2 7'b101_1011 `define SEG_OUT_3 7'b100_1111 `define SEG_OUT_4 7'b110_0110 `define SEG_OUT_5 7'b110_1101 `define SEG_OUT_6 7'b111_1101 `define SEG_OUT_7 7'b010_0111 `define SEG_OUT_8 7'b111_1111 `define SEG_OUT_9 7'b110_1111 `define SEG_OUT_ERR 7'b011_1001 module ledout(out,in); input [3:0] in; output [6:0] out; function [6:0] convert; input [3:0] in ; case (in) 0: convert = `SEG_OUT_0; 1: convert = `SEG_OUT_1; 2: convert = `SEG_OUT_2; 3: convert = `SEG_OUT_3; 4: convert = `SEG_OUT_4; 5: convert = `SEG_OUT_5; 6: convert = `SEG_OUT_6; 7: convert = `SEG_OUT_7; 8: convert = `SEG_OUT_8; 9: convert = `SEG_OUT_9; default: convert = `SEG_OUT_ERR; // If the above line is omitted, A warning messsage is shown in Synplify Pro endcase endfunction assign out=convert(in); endmodule
電卓設計演習では,デバッグを用意にするために, X Window上に構築された仮想的な電卓のGUIを用いてシミュレーションを行う.シミュレーションを行うには,このGUIは, verilogシミュレータの持つPLI(Programming Language Interface)というC言語との接続インタフェースにより記述されている. GUIはダイナミックライブラリとして構築されており, verilog実行時に動的にライブラリが読み込まれシミュレーションが行われる. gtksim.shというコマンドの引数にすべてのVerilogファイルを与えることでシミュレーションが行われる. binshifttopのシミュレーションを行うには,下記の通りにUNIXのコマンドプロンプトに入力する.
% gtksim.sh binshiftsimgtk.v binshifttop.v binshiftreg.v other.v
これにより,電卓を模したGUI(図[GUIを用いた電卓])が立ち上がる.
Qにより,シミュレーションが終了する以外は,それぞれのボタンが,回路の入力ピンに対応している.ただし, binshifttopで有効なのは10キーとCEとRSTのみである. 7セグメントLED上部の小さなLEDは,最後の電卓用のoverflowを表示する.
% cd ~/binshifttop % quartus
% gtksim.sh enzansimgtk.v enzantop.v enzan.v other.v
module inverse; reg [4:0] A,B,C;//←5ビットのレジスタ initial begin A=3;B=-2; $display("A=%d,%b, B=%d,%b",A,A,B,B); C=8-5; //←結果は3 #100 C=5-8; //←結果は-3 #100 C=-10-8; //←結果は-18(オーバーフロー) #100 C=10+10; //←結果は20(オーバーフロー) end initial $monitor("%d: ",$time,"C=%d, -%d, %b",C,~C+5'b00001,C); //↑~C+1では, 結果が32ビットになってしまうので注意する. endmodule
module inverse; reg signed [4:0] A,B,C;//←5ビットのレジスタ initial begin A=3;B=-2; $display("A=%d,%b, B=%d,%b",A,A,B,B); C=8-5; //←結果は3 #100 C=5-8; //←結果は-3 #100 C=-10-8; //←結果は-18(オーバーフロー) #100 C=10+10; //←結果は20(オーバーフロー) end initial $monitor("%d: ",$time,"C=%d, %b",C,C); //↑ Cの値を10進と2進で表示する. endmodule
% gtksim.sh calcsimgtk.v calctop.v calcsigned.v other.v