Document

計算機アーキテクチャ演習第6回
PICOのVerilog記述その2
慶応大学 天野
PICOの構成(前期の図を若干変更)
aluout
regc
outc
MUX
MUX
pc
op
com
ir
op2
op
110
ALU
001
alubin
Expander
MUX
‘2’
op2
dest
idata
src
regb
aluain
MUX
rega
adrA
adrB
regfile
ddataout
MUX
iadr
Instruction
Memory
we_
dadr
Data
Memory
ddatain
前回の演習
• JMP命令を付け加える
assign brinst = (op == BNEZ) | (op == BEQZ)|
(op==JMP);
assign pcset = ( (rega == 16'h0000)&(op == BEQZ)|
(rega != 16'h0000)& (op == BNEZ)|
(op==JMP) );
assign aluina = (stat[RF_BIT] | brinst) ? pc : rega;
assign imm16 = ((op[4:3] == 2'b00 & op != ROP) |
brinst | op == LDLI | op == LDHI) ;
assign aluinb = stat[RF_BIT] ?
op==JMP ?
imm16 ?
op == LDHI ?
16'h0002 :
{ {5{ir[10]}},ir[10:0]}:
{ {8{ir[7]}}, ir[7:0] } :
{ir[7:0],8'h00} :
regb;
挿入場所に注意
出力オリエンテッドな記述の問題点
• それぞれの出力に関して記述する
• 記述が分散的になる
• 例えばJMP命令を取り付けるのにも、色々な
所をいじる必要がある
• もっと、「XX命令の時はYYをする」という感じ
に書けないだろうか?
• 入力オリエンテッド、多入力、多出力の書き方
Function文の利用
本来、Function文は単一出力用だが、無理
やり複数出力を扱うことが可能
function [34:0] allgen;
input [StateNum-1:0] stat;
input [Opcode-1:0] op, op2;
input [DataBus-1:0] rega,regb;
begin
case(stat)
RF: allgen = {ADDOP, pc, 16'h0002};
EX: case (op)
BNEZ: allgen = {ADDOP, pc,{{8{ir[7]}},ir[7:0]}};
BEQZ: allgen = {ADDOP, pc,{{8{ir[7]}},ir[7:0]}};
LDLI: allgen = {THB, 16'bx,{{8{ir[7]}}, ir[7:0]}} ;
LDHI: allgen = {THB, 16'bx,{ir[7:0],8'b0}} ;
ROP: allgen = {op2[2:0], rega,regb} ;
default:
allgen = {op[2:0], rega,{{8{ir[7]}}, ir[7:0]}} ;
endcase
default: allgen = {op2[2:0], rega,regb};
endcase
end
endfunction
assign {com, aluina,aluinb} = allgen(stat, op, op2, rega, regb);
ALUのコマンド、入力
を同時に設定
命令単位の記述へ
function [35:0] allgen;
input [StateNum-1:0] stat;
input [Opcode-1:0] op, op2;
wireが使えないのでregを使う→前前回のバ
input [DataBus-1:0] rega,regb;
reg azero;
レルシフタ要修正
begin
azero = (rega==16'b0);
case(stat)
RF: allgen = {Disable,ADDOP, pc, 16'h0002};
EX: case (op)
if文を使ってもいい
BNEZ: allgen = {~azero,ADDOP, pc,{{8{ir[7]}},ir[7:0]}};
BEQZ: allgen = {azero, ADDOP, pc,{{8{ir[7]}},ir[7:0]}};
LDLI: allgen = {Disable,THB, 16'bx,{{8{ir[7]}}, ir[7:0]}} ;
LDHI: allgen = {Disable,THB, 16'bx,{ir[7:0],8'b0}} ;
ROP: allgen = {Disable,op2[2:0], rega,regb} ;
default:
allgen = {Disable,op[2:0], rega,{{8{ir[7]}}, ir[7:0]}} ;
endcase
default: allgen = {Disable,op2[2:0], rega,regb};
endcase
end
endfunction
assign {pcset, com, aluina,aluinb} = allgen(stat, op, op2, rega, regb);
Function文を使う場合の注意
• 入力は、指定しないとグローバル変数とマッ
チしてしまうので注意、必ず指定すること
• 出力のビット数と代入が必ず一致するように
注意、往々にしてズレる。
• regで中間出力を定義できるが、あまり複雑
にしない方が良い。
• 関連のあるものだけをまとめるのが無難。あ
まり多数の出力を一つのFunctionで扱わな
い
always文の書き方
reg pcset;
reg [ComNum-1:0] com;
reg [DataBus-1:0] aluina, aluinb;
reg文だが、レジスタではなく、
always文の出力
always @(stat or op or op2 or rega or regb)
begin
case文 if文など
全ての組み合わせで、
全ての出力を定義する
end
waiting list
入力を全て書く
always文の利用
reg pcset;
reg [ComNum-1:0] com;
reg [DataBus-1:0] aluina, aluinb;
always @(stat or op or op2 or rega or regb)
begin
case(stat)
RF: begin
pcset = 0; com = ADDOP; aluina = pc; aluinb = 16'h0002; end
EX: case (op)
BNEZ: begin
if(rega!=16'b0) pcset = Enable; else pcset = Disable;
com = ADDOP; aluina = pc;
aluinb = {{8{ir[7]}},ir[7:0]}; end
BEQZ: begin
if(rega==16'b0) pcset = Enable; else pcset = Disable;
com = ADDOP; aluina = pc;
aluinb = {{8{ir[7]}},ir[7:0]}; end
LDLI: begin
pcset =Disable; com=THB; aluina = 16'bx;
aluinb = {{8{ir[7]}}, ir[7:0]} ; end
LDHI: begin
pcset =Disable; com=THB; aluina = 16'bx;
aluinb = {ir[7:0],8'b0} ; end
ROP: begin
pcset =Disable; com=op2[2:0]; aluina= rega;
aluinb = regb; end
default: begin
pcset =Disable; com=op[2:0]; aluina= rega;
aluinb = {{8{ir[7]}}, ir[7:0]} ; end
endcase
default: begin
pcset =Disable; com=op2[2:0]; aluina= rega;
aluinb = regb; end
endcase
end
memory.v
module memory (clk,reset_,iaddr,daddr,dmwe,ddataout,idata,ddatain);
`include "pico.h"
input
clk;
input
reset_;
input
[AddrBus-1:0]
iaddr;
// Instruction Addr to I-Memory
input
[AddrBus-1:0]
daddr;
// Data Addr to D-Memory
input
[DataBus-1:0]
ddataout;
// Write Data to D-Memory
input
dmwe;
// D-Memory Write Enable
output
[DataBus-1:0]
idata;
// Instruction Data from IMemory
output
[DataBus-1:0]
ddatain;
// Read Data from D-Memory
reg
[DataBus-1:0]
imem
[MemSize-1:0];
reg
[DataBus-1:0]
dmem
[MemSize-1:0];
assignidata = imem[iaddr[8:1]];
256に設定してある
assignddatain = dmem[daddr[8:1]];
always @ ( posedge clk ) begin
if ( dmwe == Enable ) begin
dmem[daddr[8:1]] <= ddataout;
end
end
initial begin
ファイルから読込み
$readmemb ("test.prg",imem);
$readmemh ("test.dat",dmem);
readmemb:2進数
end
readmemh:16進数
endmodule
test.prgとtest.datの例
11100_001_00000000
00000_010_001_01000
00110_001_00000010
00000_011_001_01000
11100_100_00000000
00000_100_010_00110
00111_011_00000001
01001_011_11111010
00000_001_100_01001
01010_011_11111110
// LDLI r1,#0
// LD r2,(r1)
// ADDI r1,#2
// LD r3,(r1)
// LDLI r4,#0
// ADD r4,r2
// SUBI r3,#1
// BNEZ r3,-6
// ST (r1),r4
// BEQZ r3,-2
test.prg
0002
0003
0000
test.dat
テストベンチ(PICOとメモリの接続)
timescale 1ns/1ps
`
module test;
`include "pico.h"
reg
clk;
reg
reset_;
wire [DataBus-1:0]
wire [DataBus-1:0]
wire [AddrBus-1:0]
wire [AddrBus-1:0]
wire [DataBus-1:0]
wire dmwe;
idata;
ddatain;
iaddr;
daddr;
ddataout;
// Instruction Data from I-Memory
// Read Data from D-Memory
// Instruction Addr to I-Memory
// Data Addr to D-Memory
// Write Data to D-Memory
// D-Memory Write Enable
bpico16 pico ( .clk( clk ), .reset_( reset_ ), .idata( idata ), .ddatain( ddatain ),
.iaddr( iaddr ), .daddr( daddr ), .ddataout( ddataout ), .dwe( dmwe )
);
memory memory ( .clk( clk ), .reset_( reset_ ), .iaddr( iaddr ), .daddr( daddr ),
.dmwe( dmwe ), .ddataout( ddataout ), .idata( idata ), .ddatain( ddatain )
);
テストベンチ(クロックとリセット)
parameter
STEP = 100;
always # ( STEP / 2 )
clk <= ~clk;
initial begin
clk <= 1'b0;
reset_ <= Enable_;
# ( STEP )
reset_ <= Disable_;
# ( STEP * 100 );
$finish;
end
テストベンチ(表示部)
always @( negedge clk ) begin
$display( "stat:%b rfpc:%x rfir:%x r:%x %x %x %x %x %x %x %x",
pico.stat, pico.pc, pico.ir,
pico.reg0.rfile[0],
pico.reg0.rfile[1],
状態、pc, ir, register
pico.reg0.rfile[2],
fileを表示
pico.reg0.rfile[3],
pico.reg0.rfile[4],
pico.reg0.rfile[5],
pico.reg0.rfile[6],
pico.reg0.rfile[7]);
end
gktwave用のデータ格納ファイル
initial begin
$dumpfile("pico.vcd");
$dumpvars(0,pico);
end
0nsからpicoモジュールの
endmodule
データ収集
ikarus verilogの利用法
コンパイル
iverilog test.v bpico.v memory.v
– pico.h,test.prg,test.datを同じディレクトリに入れておく
または
iverilog –out ファイル名 test.v bpico.v memory.v
この時点でエラーチェックは行われる
実行
vvp a.out または
vvp ファイル名
波形を見る
gtkwave pico.vcd
テストベンチで指定したファイル名
signal search ->
Signal Search Hierarchyをクリック
Signal Search Hierarchy windows中のモジュー
ル名をクリック
表示したい信号名をクリックしてAppend
Wave window中に波形が表れる
今日の演習
JMP X PC<-PC+0x100 01111 00100000000 Jump
Function文を使ったもの、always文を使ったものの好きな方についてJMP命令を
付け加えよ。
11/15、11/22の演習
bpico.v, test.v, memory.v, pico.h, test.prg, test.datをwebから
取ってくる
1. test.prgを改造し、1からmまでの和を求めるプログラムを
作り、動作を確認せよ。mは、0番地または1番地のデータ
を用いよ。
2. bpico.vを改造し、JMPおよびJR命令を付け加えよ。
test.prgを改造してテスト用プログラムを作り動作を確認せ
よ
3. bpico.vではなく、function文を使ったbpicof.v, always文を
使ったbpicoa.vを使っても良い
この間と同じグループで良い
11/29までに、授業webに1のtest.prgと2のbpico.vを別々に提
出のこと