計算機アーキテクチャ演習第 4 回 アキュムレータマシン
DESCRIPTION
計算機アーキテクチャ演習第 4 回 アキュムレータマシン. 慶應義塾大学 理工学部 情報工学科 天野. always 文を使った順序回路. assign 文を使って常に出力する組み合わせ回路と違って順序回路はレジスタに値をセットするタイミングを示す必要がある。 reg [3:0] accum; always@(posedge clock) begin accumTRANSCRIPT
2007/10/11 1
計算機アーキテクチャ演習第 4回アキュムレータマシン
慶應義塾大学 理工学部 情報工学科天野
2007/10/11 2
always 文を使った順序回路 assign 文を使って常に出力する組み合わせ回路と
違って順序回路はレジスタに値をセットするタイミングを示す必要がある。
reg [3:0] accum;always@(posedge clock) begin accum <= alu0(accum,inb,com);end
clock が L→H に変化した際に生じる reg への値のセットについての操作を begin end 内に記述
値のセットは<=を利用 if, case が利用可 複数のレジスタを同じ文中で扱える。でも注意! タイミング記述
negedge : 立下り or : 値のセットするタイミングが複数ある場合
2007/10/11 3
同期リセット、非同期リセット
always@(posedge clock or negedge rst_) begin if(rst_ == `Enable_) accm <= 4’b0000; else accum <= alu0(accum, inb, com);end
rst_ が L になったらすぐにリセット:非同期
always@(posedge clock) begin if(rst_ == `Enable_) accm <= 4’b0000; else accum <= alu0(accum, inb, com);end
rst_ が L になり、クロックが立ち上がったときにリセット:同期
2007/10/11 4
アキュムレータデータパスの記述
module acdpath(din, com, acout, clock); input [3:0] din; input [2:0] com; output [3:0] acout; input clock; reg [3:0] accum; wire [3:0] aluout; assign acout = accum; ALU alu0(.A(accum), .B(din), .COM(com), .ALUOUT(aluout) ); always@(posedge clock) begin accum <= aluout; end
endmodule
本当はちゃんと parameter で定義して
階層記述: ALU の利用
2007/10/11 5
階層記述 他のモジュールを利用する
実は前回のテストベンチで使っていた
ALU alu0(.A(accum), .B(din), .COM(com), .ALUOUT(aluout) );
モジュール名:定義したものと同一にする実体名:この階層での名前、複数用いる場合、 重なってはならない
モジュールの入出力名:定義したものと同一この階層での信号名:出力は wire で受ける
ALUOUTA B
COM alu0com
aluout
accum din
2007/10/11 6
記述したデータパス
accum
ALU
din
acout
com
aluout
春学期プリント第 2 回 図3までこれでできたことになる
2007/10/11 7
メモリの記述
reg の配列で記述reg [3:0] mem[0:15];
4 ビット幅、 16 エントリのメモリが宣言される 深さ方向は、2のべき乗でなくても良いが、半端
な値にしても通常意味はない
assign dr = mem[adr]; 読み出しmem[adr] <= dw; 書き込み(通常 always 文
中) 通常合成はしないので注意!(今回は小さい
のでやってしまうが、、)
bit 幅
深さエントリ数
2007/10/11 8
井口先生の第 1 回目の資料を改造RAM (RWM) の入出力 クロック入力付きの場合
AD[3:0]
DOUT[3:0]
4
4WE
4DIN[3:0]
1. WRITE: メモリの指定番地に値を書き込む• 書き込む番地を AD に入力 , 書き込む値を DIN に入力• WE = 1 とする.• CLK のネガティブ・エッジで書き込む
2. READ: メモリから値を読み出す• 読み出したい番地をADに入力• WE = 0 (書き込み以外はWEは0にしておく)
CLK
2007/10/11 9
井口先生の第 1 回目の資料よりData Memory の初期化
module RAM16_4(CLK, WE, ADDRESS, DIN, DOUT);// register file input CLK; input WE; input [3:0] ADDRESS; input [3:0] DIN; output [7:0] DOUT; reg [3:0] MEMCELL [0:15]; assign DOUT = MEMCELL[ADDRESS]; always @(negedge CLK) begin if (WE) MEMCELL[ADDRESS] <= DIN; end
// 本来RAMのデータを初期化したい時は外部に書き込む// 回路を付けるのだが,今回は簡単のためにここに初期化// の手続きを書くことにする.次ページ参照のこと.
endmodule
この例はクロックの立下りで書込みを行っている.各自の設計にあわせて立上りにするか立下りにするかを決めること.
2007/10/11 10
井口先生の第 1 回目の資料よりData Memory の記述例(1)
module RAM16_4(CLK, WE, ADDRESS, DIN, DOUT);// メモリの記述のあと, endmodule との間に以下の// 初期化の記述を書く.この例では0番地に 4H , 1 番地に// 7H ,2番値に 1H を入れている.これに先立ち全ての// メモリセルを0に初期化していることに注意せよ.
integer i; initial begin for (i=0; i<16; i=i+1)begin MEMCELL[i]=0; end MEMCELL[0] = 4'b0100; // X = 4H MEMCELL[1] = 4'b0111; // Y = 7H MEMCELL[2] = 4'b0001; // Z = 01H MEMCELL[3] = 4'b0000; // Answer end
endmodule
2007/10/11 11
井口先生の第 1 回目の資料よりData Memory の記述例( 2 )
module RAM16_4(CLK, WE, ADDRESS, DIN, DOUT);// メモリの記述のあと, endmodule との間に以下の// 初期化の記述を書く.この例ではメモリの内容は,同じ// folder の test.txt というファイルから.
initial $readmemb("test.txt",MEMCELL);endmodule
0100011100010000...0000
test.txt の中身16行全て記述する.
2007/10/11 12
メモリ付データパスmodule acdpath(adr, com, acout,clock); input [3:0] adr; input [3:0] com; output [3:0] acout; input clock; reg [3:0] accum; wire [3:0] aluout, ddata; assign acout = accum; ALU alu0(.A(accum), .B(ddata), .COM(com[2:0]), .ALUOUT(aluout) ); RAM16_4 dmem(.CLK(clock), .WE(we), .ADDRESS(adr), .DIN(accum), .DOUT(ddata)); WE = com[3] ; always@(posedge clock) begin if (~com[3]) accum <= aluout; endendmodule
2007/10/11 13
メモリ付データパス
accum
ALU
DataMemory
weddata
adr
aout
春学期プリント第 2 回 図 5 までこれでできたことになる
comcom[2:0]
com[3]
2007/10/11 14
アキュムレータマシン
accumpc
+
‘ 1’
ALU
ir
InstructionMemory
DataMemory
op.code
operand
we_ddata
dadr
idata
iadr
acout
2007/10/11 15
井口先生の第 1 回目の資料ROM の入出力
AD[0]AD[1]AD[2]AD[3]
DOUT[0]
DOUT[1]
DOUT[2]
DOUT[3]
DOUT[4]
DOUT[5]
DOUT[6]DOUT[7]
AD[3:0]
DOUT[7:0]
4
8
番地 (Address) に値を入力すると該当番地に格納されている内容が DOUTに出力される .
2007/10/11 16
井口先生の第 1 回目の資料Instruction Memory の記述module ROM16_8(AD, DOUT);// Instruction Memory input [3:0] AD; output [7:0] DOUT; function [7:0] rom; input [3:0] address; case(address) 0: rom = 8'b????_????; 1: rom = 8'b????_????;// ここに値を埋める 15: rom = 8'b????;
default: rom = 8'b0000_0000; endcase endfunction
assign DOUT = rom(AD);endmodule
ここの部分に命令を各自で入れること!
2007/10/11 17
状態遷移
InstructionFetch
Execution
rst_
pc←pc + 1ir ← idata
BEQ: if (accum == 0) pc← ir[3:0]BNQ: if (accum != 0) pc← ir[3:0]ST: we_ = Lelse: accum ← ALU 出力
2007/10/11 18
アキュムレータの記述( 1 ) parameter Enable = 1’b1 ; parameter Disable = 1’b0 ; parameter Enable_ = 1’b0 ; parameter Disable_ = 1’b1 ; parameter DataBus=4 ; parameter InstBus=8 ; parameter STNUM=2 ; parameter IF=2’b01 ; parameter EX=2’b10 ; parameter EX_BIT=1‘b1 ;
parameter BEQ= 4’b1010 ; parameter BNQ= 4’b1011 ;
2007/10/11 19
アキュムレータの記述( 2 )module accum(clock, rst_, acout);input clock, rst_;output [DataBus-1:0] acout;wire [DataBus-1:0] ddata;wire [InstBus-1:0] idata;wire [DataBus-1:0] dadr;wire we;reg [DataBus-1:0] accum; // Accumulatorreg [DataBus-1:0] pc; // Program Counterreg [InstBus-1:0] ir; // Instruction Registerreg [STNUM-1:0] stat; // State registerwire [DataBus-1:0] aluout;assign acout = accum;assign dadr = ir[3:0];assign we = stat[EX_BIT] & (ir[7:4] == ST);ALU alu0(.A(accum), .B(ddata), .COM(ir[6:4]), .ALUOUT(aluout));ROM16_8 imem(.AD(pc), .DOUT(idata));RAM16_4 dmem (.CLK(clock), .WE(we), .ADDRESS(dadr),
.DIN(accum), .DOUT(ddata));
2007/10/11 20
アキュムレータの記述( 2 )always@(posedge clock) begin if(rst_ == Enable_) begin
stat <= IF;pc <= 4'b0000; end
else case (stat) //Case 文 IF: begin ir <= idata;
pc <= pc+1; stat <= EX; end
EX: begin case (ir[7:4]) //Case 文入れ子
BEQ: if (accum == 4'b0000) pc <= ir[3:0]; BNE: if (accum != 4'b0000) pc <= ir[3:0]; default: if(ir[7]==1'b0) accum <= aluout;endcasestat <= IF; end
endcaseendendmodule
この記述は命令により様々なレジスタを
制御している
リソースシュアリングが可能だが、やりすぎると
バグの元なので注意!
2007/10/11 21
テストベンチ`timescale 1ns/1psmodule accum_test;
parameter STEP = 10;reg rst_, clk;
wire [3:0] acout;accum ac0( .clock( clk ), .rst_( rst_ ), .acout (acout) );
always #( STEP / 2 ) beginclk <= ~clk; end
initial begin#0
clk <= 1’b0;rst_ <= Enable_;
#(STEP/4)#(STEP)
rst_ <= Disable_;#(STEP*100)
$finish;endalways @( negedge clk ) begin
$display( "stat = %b pc = %x ir = %x, accum = %x", ac0.stat,ac0.pc, ac0.ir, acout);
end
2007/10/11 22
演習 アキュムレータに SUBI 命令を付け加
えよ