# 數位系統實驗報告Lab16 :::info 學號: B093040044 系級: 資工113 姓名: 蔡明軒 ::: ``` 實驗日期: 1/3 ``` ## 實驗一 ### 內容 - 使用 Verilog HDL、Structural modeling , 設計並驗證一個 4x4 RAM ### 過程 1. 由於有 4 個 word ,我們需要一個 2x4 的 Decoder ```verilog= module decoder_2x4(output[3:0] D,input A,B,E); assign D[0] = ~A & ~B & E, D[1] = ~A & B & E, D[2] = A & ~B & E, D[3] = A & B & E; endmodule ``` 2. 撰寫 RAM 儲存單元 ,每個單元只儲存一個 bit 的資料 ```verilog= module BC (Enable, ReadWrite, DataIn, DataOut); input Enable, ReadWrite; input DataIn; output DataOut; reg DataOut; reg Mem ; always @ (Enable or ReadWrite) if (Enable) if (ReadWrite) DataOut = Mem; else Mem = DataIn; else DataOut = 1'bz; endmodule ``` 3. 使用 16 個記憶體單元,將這些單元接上對應的 decoder 位置,以及 ReadWrite,DataIn,DataOut port ```verilog= module Ram_4x4 (output[3:0] DataOut,input[3:0] DataIn,input[1:0] AddressInputs, input MemoryEnable,ReadWrite); wire[3:0] DecodeRes; decoder_2x4 d0(DecodeRes,AddressInputs[1],AddressInputs[0],MemoryEnable); BC u00(DecodeRes[0],ReadWrite,DataIn[0],DataOut[0]), u01(DecodeRes[0],ReadWrite,DataIn[1],DataOut[1]), u02(DecodeRes[0],ReadWrite,DataIn[2],DataOut[2]), u03(DecodeRes[0],ReadWrite,DataIn[3],DataOut[3]), u10(DecodeRes[1],ReadWrite,DataIn[0],DataOut[0]), u11(DecodeRes[1],ReadWrite,DataIn[1],DataOut[1]), u12(DecodeRes[1],ReadWrite,DataIn[2],DataOut[2]), u13(DecodeRes[1],ReadWrite,DataIn[3],DataOut[3]), u20(DecodeRes[2],ReadWrite,DataIn[0],DataOut[0]), u21(DecodeRes[2],ReadWrite,DataIn[1],DataOut[1]), u22(DecodeRes[2],ReadWrite,DataIn[2],DataOut[2]), u23(DecodeRes[2],ReadWrite,DataIn[3],DataOut[3]), u30(DecodeRes[3],ReadWrite,DataIn[0],DataOut[0]), u31(DecodeRes[3],ReadWrite,DataIn[1],DataOut[1]), u32(DecodeRes[3],ReadWrite,DataIn[2],DataOut[2]), u33(DecodeRes[3],ReadWrite,DataIn[3],DataOut[3]); endmodule ``` 4. 撰寫 test bench 檔案 ```verilog= `timescale 1ns / 1ps module tb; reg Enable, ReadWrite; reg [3: 0] DataIn; reg [1: 0] Address; wire [3: 0] DataOut; Ram_4x4 M0(DataOut,DataIn,Address,Enable, ReadWrite); initial #150 $finish; initial begin Enable = 1; ReadWrite = 0; Address = 0; DataIn = 0; #10 ReadWrite=1'b0; //Write #10 Address =2'b01; DataIn =4'b0001; #10 Address =2'b10; DataIn =4'b0010; #10 Address =2'b11; DataIn =4'b0011; #10 Address =2'b00; DataIn =4'b0100; #10 Address =2'bxx; DataIn =4'bxxxx; #10 ReadWrite=1'b1; //Read #10 Address =2'b00; #10 Address =2'b01; #10 Address =2'b10; #10 Address =2'b11; end endmodule ``` ### 結果 - 預期結果,DataOut輸出對應Address的內容要和先前對應Address最後輸入的內容相同 | Clock | ReadWrite | Address | DataIn | DataOut | |:-----:|:---------:|:-------:|:------:|:-------:| | #0 | 0 | 00 | 0000 | X | | #20 | 0 | 01 | 0001 | X | | #30 | 0 | 10 | 0010 | X | | #40 | 0 | 11 | 0011 | X | | #50 | 0 | 00 | 0100 | X | | #60 | 0 | X | X | X | | #70 | 1 | X | X | X | | #80 | 1 | 00 | X | 0100 | | #90 | 1 | 01 | X | 0001 | | #100 | 1 | 10 | X | 0010 | | #110 | 1 | 11 | X | 0011 | - 輸出結果和上述預期結果相同 ![](https://i.imgur.com/yBT12b4.png) ## 實驗二 ### 內容 - 使用 Verilog HDL、Behavioral modeling , 設計並驗證一個 8x8 register file with write port and 2 read ports ### 過程 1. 撰寫 8x8 的 Register File,直接宣告一個 8x8 大小的 reg ,將 RAA,RAB 指到的位置,輸出到DATA_A,DATA_B,若 WE 為真,這個module會在正緣的時候寫入 DATA_W ```verilog= module regfile(output [7:0] DATA_A,DATA_B,input[2:0] WA, RAA,RAB, input[7:0] DATA_W,input WE,REA, REB, clk, rst); reg [7:0] registers[7:0]; assign DATA_A = registers[RAA]; assign DATA_B = registers[RAB]; always @ (posedge clk or negedge rst) begin if (~rst) registers[0] = 0; else begin if (WE) registers[WA] <= DATA_W; end end endmodule ``` 2. 撰寫 test bench檔案 ```verilog= `timescale 1ns / 1ps module tb; wire [7:0] DATA_A,DATA_B; reg[2:0] WA, RAA,RAB; reg[7:0] DATA_W; reg WE, REA, REB, clk, rst; regfile R0(DATA_A,DATA_B,WA, RAA,RAB, DATA_W,WE,REA, REB, clk, rst); initial #130 $finish; initial begin clk = 0; forever #5 clk = ~clk; end initial fork rst = 0; WE = 1'b1; REA=1'b0; REB=1'b0; #2 rst = 1; WA =3'b000;DATA_W =8'b00000000; #10 WA =3'b001; #10 DATA_W =8'b00000001; #20 WA =3'b010; #20 DATA_W =8'b00000010; #30 WA =3'b011; #30 DATA_W =8'b01010111; #40 WA =3'b100; #40 DATA_W =8'b01001000; #50 WA =3'b101; #50 DATA_W =8'b01111100; #60 WA =3'b110; #60 DATA_W =8'b00110101; #70 WA =3'b111; #70 DATA_W =8'b11111111; #80 WE=1'b0; #80 REA=1'b1; #80 REB=1'b1; #80 WA =3'bxxx;#80 DATA_W =8'bxxxxxxxx; #90 RAA =3'b000;#90 RAB=3'b001; #100 RAA =3'b010;#100 RAB=3'b011; #110 RAA =3'b100;#110 RAB=3'b101; #120 RAA =3'b110;#120 RAB=3'b111; join endmodule ``` ### 結果 - 80ns 前輸入進 Register File 的資料 | Address(WA) | DATA_W | |:-----------:|:--------:| | 000 | 00000000 | | 001 | 00000001 | | 010 | 00000010 | | 011 | 01010111 | | 100 | 01001000 | | 101 | 01111100 | | 110 | 00110101 | | 111 | 11111111 | - 在90ns後,DATA_A,DATA_B的輸出皆與對應的位址(RAA, RAB)的資料相同 ![](https://i.imgur.com/Oxcj84f.png) ## 實驗心得 >這次的實驗內容為兩種常見的記憶元件,RAM 以及 Register File,後者和前者最大的差別是,它讀入和寫入的時候用到的Decoder是分離的,這次因為是實作 2 read port 1 write port 的register file,因此它會需要有三個 3x8 Decoder,從這樣看來,register file會用到更多電晶體(多了幾組 Decoder),但也得到了可以在一個clock 讀取多筆資料的優點。 >在第一個實驗中,由於會需要用到16個RAM單元,我一開始想要直接做成陣列的形式,但是在實作的過程中碰到了困難,因為建立每個 RAM 單元的時候,會需要綁定port,而且我也不能在宣告陣列的時候就直接綁好每個單元的port,因此最後我決定改用最簡單的方式,乾脆宣告16個名字不同的RAM單元,個別綁定對應的port,最後也成功完成了第一個實驗。 >在第二個實驗,我在觀察PPT給的code中,發現原來陣列並不一定要用整數當索引值,用一個二進位值當索引值的時候,Verilog 似乎會幫你轉換成十進位,接著對對應的十進位索引值進行存取,這樣就可以直接做到 Decoder 的效果。