計算機アーキテクチャ演習第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を別々に提 出のこと
© Copyright 2024 ExpyDoc