計算機アーキテクチャ演習第4回 アキュムレータマシン 慶應義塾大学 理工学部 情報工学科 天野 2007/10/11 1 always文を使った順序回路 assign文を使って常に出力する組み合わせ回路と 違って順序回路はレジスタに値をセットするタイミング を示す必要がある。 reg [3:0] accum; always@(posedge clock) begin accum <= alu0(accum,inb,com); end clockがL→Hに変化した際に生じるregへの値のセット についての操作をbegin end内に記述 値のセットは<=を利用 if, caseが利用可 複数のレジスタを同じ文中で扱える。でも注意! タイミング記述 2007/10/11 negedge : 立下り or : 値のセットするタイミングが複数ある場合 2 同期リセット、非同期リセット 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 2007/10/11 rst_がLになり、クロックが立ち上がったときにリセット: 同期 3 アキュムレータデータパスの記述 module acdpath(din, com, acout, clock); input [3:0] din; 本当はちゃんとparameterで定義して input [2:0] com; output [3:0] acout; input clock; reg [3:0] accum; wire [3:0] aluout; 階層記述:ALUの利用 assign acout = accum; ALU alu0(.A(accum), .B(din), .COM(com), .ALUOUT(aluout) ); always@(posedge clock) begin accum <= aluout; end endmodule 2007/10/11 4 階層記述 他のモジュールを利用する 実は前回のテストベンチで使っていた モジュール名:定義したものと同一にする 実体名:この階層での名前、複数用いる場合、 重なってはならない ALU alu0(.A(accum), .B(din), .COM(com), .ALUOUT(aluout) ); モジュールの入出力名:定義したものと同一 この階層での信号名:出力はwireで受ける aluout com 2007/10/11 ALUOUT COM alu0 A B accum din 5 記述したデータパス aluout com acout ALU accum din 春学期プリント第2回 図3までこれでできたことになる 2007/10/11 6 メモリの記述 bit幅 regの配列で記述 reg [3:0] mem[0:15]; 深さ エントリ数 4ビット幅、16エントリのメモリが宣言される 深さ方向は、2のべき乗でなくても良いが、半端な値 にしても通常意味はない assign dr = mem[adr]; 読み出し mem[adr] <= dw; 書き込み(通常always文中) 通常合成はしないので注意!(今回は小さいの でやってしまうが、、) 2007/10/11 7 井口先生の第1回目の資料を改造 RAM (RWM)の入出力 クロック入力付きの場合 4 AD[3:0] 4 DIN[3:0] WE DOUT[3:0] CLK 4 1. WRITE: メモリの指定番地に値を書き込む • 書き込む番地をADに入力, 書き込む値をDINに入力 • WE = 1 とする. • CLKのネガティブ・エッジで書き込む 2. READ: メモリから値を読み出す • 読み出したい番地をADに入力 • WE = 0 (書き込み以外はWEは0にしておく) 2007/10/11 8 井口先生の第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 9 井口先生の第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 10 井口先生の第1回目の資料より Data Memoryの記述例(2) module RAM16_4(CLK, WE, ADDRESS, DIN, DOUT); // メモリの記述のあと,endmoduleとの間に以下の // 初期化の記述を書く.この例ではメモリの内容は,同じ // folderの test.txtというファイルから. initial $readmemb("test.txt",MEMCELL); endmodule 0100 0111 0001 0000 . . . 0000 2007/10/11 test.txt の中身 16行全て記述する. 11 メモリ付データパス 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; end endmodule 2007/10/11 12 メモリ付データパス com com[2:0] ALU accum com[3] aout we adr ddata Data Memory 春学期プリント第2回 図5までこれでできたことになる 2007/10/11 13 アキュムレータマシン ir op.code ALU ‘1’ accum pc operand + idata iadr 2007/10/11 Instruction Memory acout we_ dadr ddata Data Memory 14 井口先生の第1回目の資料 ROMの入出力 AD[0] AD[1] AD[2] AD[3] 2007/10/11 DOUT[0] DOUT[1] DOUT[2] DOUT[3] DOUT[4] DOUT[5] DOUT[6] DOUT[7] 4 AD[3:0] 8 DOUT[7:0] 番地(Address)に値を入力 すると該当番地に格納され ている内容がDOUTに出力 される. 15 井口先生の第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 16 状態遷移 rst_ Instruction Fetch pc←pc+1 ir ← idata 2007/10/11 Execution BEQ: if (accum == 0) pc← ir[3:0] BNQ: if (accum != 0) pc← ir[3:0] ST: we_ = L else: accum ← ALU出力 17 アキュムレータの記述(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 18 アキュムレータの記述(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; // Accumulator reg [DataBus-1:0] pc; // Program Counter reg [InstBus-1:0] ir; // Instruction Register reg [STNUM-1:0] stat; // State register wire [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 19 アキュムレータの記述(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; endcase stat <= IF; end endcase end endmodule 2007/10/11 20 テストベンチ `timescale 1ns/1ps module accum_test; parameter STEP = 10; reg rst_, clk; wire [3:0] acout; accum ac0( .clock( clk ), .rst_( rst_ ), .acout (acout) ); always #( STEP / 2 ) begin clk <= ~clk; end initial begin #0 clk <= 1’b0; rst_ <= Enable_; #(STEP/4) #(STEP) rst_ <= Disable_; #(STEP*100) $finish; end always @( negedge clk ) begin $display( "stat = %b pc = %x ir = %x, accum = %x", ac0.stat,ac0.pc, ac0.ir, acout); end 2007/10/11 21 演習 2007/10/11 アキュムレータにSUBI命令を付け加えよ 22
© Copyright 2024 ExpyDoc