MacでVerilogのシミュレーションをしてみる2
MacでVerilogのシミュレーションをしてみる1 - k-igrsの日記
の続き。
テストベンチにメモリを接続し、プログラムを読み込んで実行してみる。
まず、メモリを記述する。
- 16bit×1024word
- データの読み出しはアドレスを指定すれば、対応するデータを出力する
- データの書き込みはクロックの立ち上がりでWRBが[L]の時、対応するアドレスにデータを書き込む
RTLは以下のように記述。
module MEMORY ( ADR, WRB, CK, DI, DO ); input [9:0] ADR; input [15:0] DI; input WRB,CK; output [15:0] DO; wire [9:0] ADR; wire [15:0] DI,DO; wire WRB,CK; reg [15:0] MEM[1023:0]; assign DO = MEM[ADR]; always @( posedge CK ) if ( WRB == 1'b0) MEM[ADR] <= DI; endmodule
ステートマシンの動作に従って処理をする回路、すなわちCPUを記述する。モジュールとIOは以下の通り。
module CPU ( ADR, DI, DO, RDB, WRB, CK, RB ); input CK,RB; input [15:0] DI; output [15:0] DO; output [9:0] ADR; output RDB,WRB;
ステートマシンを呼び出す。
state_m inst_state_m ( .CK(CK), .RB(RB), .PC(PC), .Q(Q) );
CPUが読み込みを行なっている信号RDBを作成する。今回はFetch(0000b)の時にアクティブ[L]にする。
// Make Read pulse assign pre_rdb = (Q == 4'b1111) ? 1'b0 : (Q == 4'b0010) ? 1'b0 : 1'b1; always @( posedge CK, negedge RB ) if ( RB == 1'b0 ) RDB <= 1'b1; else RDB <= pre_rdb;
Fetchが終了したらオペコード(上位8bit)とオペランド(下位8bit)をラッチする。
always @( posedge CK, negedge RB ) if ( RB == 1'b0 ) begin op_code <= 8'h00; op_rand <= 8'h00; end else if ((Q==4'b0000) && (RDB==1'b0)) begin op_code <= DI[15:8]; op_rand <= DI[7:0]; end
アドレスはPCの値を出力する。
assign ADR = PC;
テストベンチにCPUとメモリを読み込んでテストベンチ内で結線する。
reg CK, RB; wire [9:0] w_ADR; wire w_RDB,w_WRB; wire [15:0] w_DI,w_DO; CPU inst_CPU( .ADR(w_ADR), .RDB(w_RDB), .WRB(w_WRB), .DI(w_DI), .DO(w_DO), .CK(CK), .RB(RB) ); MEMORY inst_memory( .ADR(w_ADR), .WRB(w_WRB), .CK(CK), .DI(w_DO), .DO(w_DI) );
テストベンチ内でメモリの初期データをあらかじめ読み込んでおく。
initial begin $readmemh("memdata.txt",inst_memory.MEM); end
データは16進数で記述しておく。
0000
1101
2202
3303
コンパイルして実行して結果を確認する。
iverilog -o cputest -s CPU_TEST cputest.v cpu.v state_m.v mem.v
vvp cputest out
実行結果
サイクルの進行に従って、メモリから順にデータを読み込んでオペコードとオペランドをラッチしていることがわかる。