トップ:http://galaxy.u-aizu.ac.jp/note/wiki/CAEX2015 = メモリとレジスタ = = 課題1 レジスタの利用方法 = 以下のテストベンチは、レジスタファイルをインスタンス化して、$a0レジスタに"0xffffffff"を書き込んでいる。 {{{ `timescale 1ns/1ps `include "Registers.v" module RegTest; reg [4:0] read_adr1, read_adr2, write_adr; reg [31:0] write_data; reg write_enable; reg ck,clear; wire [31:0] read_data1, read_data2; Registers regs(read_adr1, read_adr2, write_data, write_enable, write_adr, ck, clear, read_data1, read_data2); initial begin $dumpfile("RegTest.vcd"); $dumpvars(0, RegTest); #0 ck = 1'b1; clear = 1'b1; #110 clear = 1'b0; #190 read_adr1 = 5'b00100; #100 write_enable = 1'b1; write_adr = 5'b00100; write_data = 32'hffffffff; $display("%x %x",read_adr1, read_data1); #100 write_enable = 1'b0; $display("%x %x",read_adr1, read_data1); #900 $finish; end // initial begin always #50 ck = ~ck; endmodule }}} これを参考にして、以下のテーブルに示すように、レジスタに値の値を書き込んで、読み出すテストベンチを作成し実行したうえで、クロック信号(ck)、読み出しているレジスタのアドレス(read_adr1)と読み出し結果(read_data1)の波形を確認しなさい。波形には、この三つの信号のみを表示すること。表示する順番は、小さいアドレスから大きいアドレスになるようにすること。なお、表示している信号名がわかるようにすること。 ||レジスタ|| 値|| || $sp || 0xfffff || || $v0 || 0xfafa || || $v1 || 0x1010 || || $t0 || 0xffffffff || || $t1 || 0xaaaaaaaa || || $ra || 0x98765432 || || $t2 || 0x98765432 || || $t3 || 0x12121 || == 波形の例 == 以下のように各レジスタにデータを書き込んだ場合: || $at || 0xf || || $v0 || 0xff || || $v1 || 0xfff || || $a0 || 0xffff || 実行結果の波形の例: [[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex06%E8%AA%B2%E9%A1%8C2015/comparch_ex6_reg.png)]] = 課題2 メモリの利用方法 = 以下のテストベンチファイルでは、レジスタファイルとメモリとALUをインスタンス化し、テストするためのテンプレートである。 {{{ `timescale 1ns/1ps `include "Registers.v" `include "Memory.v" `include "ALU.v" module MemTest; // for Memory reg [31:0] address; reg [31:0] write_data; reg write_enable, read_enable; reg ck; wire [31:0] read_data; // for Registers reg [4:0] read_adr1_reg, read_adr2_reg, write_adr_reg; reg [31:0] write_data_reg; reg write_enable_reg; reg clear_reg; wire [31:0] read_data1_reg, read_data2_reg; // for ALU reg [31:0] A, B; reg [3:0] ALUop; wire Zero; wire [31:0] Result; Memory mem(address, write_data, read_data, write_enable, read_enable, ck); Registers regs(read_adr1_reg, read_adr2_reg, write_data_reg, write_enable_reg, write_adr_reg, ck, clear_reg, read_data1_reg, read_data2_reg); ALU alu(A, B, ALUop, Result, Zero); initial begin $dumpfile("MemTest.vcd"); $dumpvars(0, MemTest); // data segment Mem.cell['h00005000] = 32'h0000000a; Mem.cell['h00005004] = 32'h0000000b; Mem.cell['h00005008] = 32'h00000000; Mem.cell['h00005010] = 32'h00000000; Mem.cell['h00005014] = 32'h00000000; Mem.cell['h00005018] = 32'h00000000; #0 ck = 1'b1; clear_reg = 1'b1; read_enable = 1'b0; address = 32'h00000000; write_enable_reg = 1'b0; write_adr_reg = 5'b00000; write_data_reg = 32'h00000000; #110 clear_reg = 1'b0; #190 // read memory at 0x5000 read_enable = 1'b1; address = 32'h00005000; #100 // write data to $v0 and read memory at 0x5004 write_enable_reg = 1'b1; write_adr_reg = 5'b00010; write_data_reg = read_data; #100 read_enable = 1'b0; write_enable_reg = 1'b0; #100 read_adr1_reg = 5'b00010; #100 $display("$v0 = %x",read_data1_reg); #2000 $finish; end // initial begin always #50 ck = ~ck; endmodule }}} 実行結果は以下のようになるはずである。 {{{ % ncverilog test_mem.v ....省略 ncsim> run $v0 = 0000000a ....省略 }}} ちなみに、以下の部分でメモリからデータを読み出し、レジスタファイル($v0)に書き込んでいる。 {{{ #190 // read memory at 0x5000 read_enable = 1'b1; address = 32'h00005000; #100 // write data to $v0 write_enable_reg = 1'b1; write_adr_reg = 5'b00010; write_data_reg = read_data; #100 read_enable = 1'b0; write_enable_reg = 1'b0; }}} 実行結果の波形の例: [[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex06%E8%AA%B2%E9%A1%8C2015/comparch_ex6_mem.png)]] このテンプレートを元にして、アドレス0x5000と0x5004にあるデータを演算した結果を、再びメモリに書き込むテストベンチを作成せよ。格納アドレスと演算結果の対応は以下の通りとする。特に、レジスタへの読み書き、演算をして結果をメモリに書き込む部分の波形を確認すること。 || 0x5008 || 加算 || || 0x500c || 減算 || || 0x5010 || AND演算 || || 0x5014 || 3*"0x5000のデータ"+"0x5004のデータ" ||