Verilog

計算機アーキテクチャ演習第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