220 likes | 368 Views
計算機アーキテクチャ演習第 4 回 アキュムレータマシン. 慶應義塾大学 理工学部 情報工学科 天野. always 文を使った順序回路. assign 文を使って常に出力する組み合わせ回路と違って順序回路はレジスタに値をセットするタイミングを示す必要がある。 reg [3:0] accum; always@(posedge clock) begin accum <= alu0(accum,inb,com); end clock が L→H に変化した際に生じる reg への値のセットについての操作を begin end 内に記述 値のセットは<=を利用
E N D
計算機アーキテクチャ演習第4回アキュムレータマシン計算機アーキテクチャ演習第4回アキュムレータマシン 慶應義塾大学 理工学部 情報工学科 天野
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 : 値のセットするタイミングが複数ある場合
同期リセット、非同期リセット always@(posedge clockor 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になり、クロックが立ち上がったときにリセット:同期
アキュムレータデータパスの記述 • 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の利用
階層記述 • 他のモジュールを利用する • 実は前回のテストベンチで使っていた モジュール名:定義したものと同一にする 実体名:この階層での名前、複数用いる場合、 重なってはならない • ALU alu0(.A(accum), .B(din), .COM(com), .ALUOUT(aluout) ); モジュールの入出力名:定義したものと同一 この階層での信号名:出力はwireで受ける aluout ALUOUT com alu0 COM A B accum din
記述したデータパス aluout com ALU acout accum din 春学期プリント第2回 図3までこれでできたことになる
メモリの記述 bit幅 深さ エントリ数 • regの配列で記述 reg [3:0] mem[0:15]; • 4ビット幅、16エントリのメモリが宣言される • 深さ方向は、2のべき乗でなくても良いが、半端な値にしても通常意味はない assign dr = mem[adr]; 読み出し mem[adr] <= dw; 書き込み(通常always文中) • 通常合成はしないので注意!(今回は小さいのでやってしまうが、、)
井口先生の第1回目の資料を改造RAM (RWM)の入出力 クロック入力付きの場合 4 AD[3:0] 4 DIN[3:0] 4 WE DOUT[3:0] CLK • WRITE: メモリの指定番地に値を書き込む • 書き込む番地をADに入力, 書き込む値をDINに入力 • WE = 1 とする. • CLKのネガティブ・エッジで書き込む • READ: メモリから値を読み出す • 読み出したい番地をADに入力 • WE = 0 (書き込み以外はWEは0にしておく)
井口先生の第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 この例はクロックの 立下りで書込みを 行っている. 各自の設計にあわ せて立上りにするか 立下りにするかを 決めること.
井口先生の第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
井口先生の第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 test.txt の中身 16行全て記述する.
メモリ付データパス 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
メモリ付データパス com[2:0] com ALU accum com[3] ddata aout we Data Memory adr 春学期プリント第2回 図5までこれでできたことになる
アキュムレータマシン ir op.code ALU ‘1’ accum pc operand + idata ddata acout we_ Instruction Memory Data Memory iadr dadr
井口先生の第1回目の資料ROMの入出力 4 AD[3:0] 8 AD[0] DOUT[0] DOUT[7:0] AD[1] DOUT[1] AD[2] DOUT[2] AD[3] DOUT[3] DOUT[4] DOUT[5] DOUT[6] DOUT[7] 番地(Address)に値を入力すると該当番地に格納されている内容がDOUTに出力される.
井口先生の第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 ここの部分に 命令を各自で 入れること!
状態遷移 rst_ Instruction Fetch Execution pc←pc+1 ir ←idata BEQ: if (accum == 0) pc← ir[3:0] BNQ: if (accum != 0) pc← ir[3:0] ST: we_ = L else: accum ← ALU出力
アキュムレータの記述(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;
アキュムレータの記述(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));
アキュムレータの記述(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 この記述は命令により様々なレジスタを 制御している リソースシュアリングが 可能だが、やりすぎると バグの元なので注意!
テストベンチ `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
演習 • アキュムレータにSUBI命令を付け加えよ