123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- //This testbench verifies all implemented functions of the Module "SPI-FRAM-Module". That contains Read/Write to memory, Status register read and Hibernation.
-
- `timescale 1us/1ns
-
- module SPI_FRAM_tb;
- reg SI, SO; //init all registers that are connected to the identical named ports of the FRAM-Module.
- reg SCK, nCS;
- reg [7:0] opcode;
- reg [7:0] mem_data [1023:0] ;
- reg [23:0] addr; //3 Byte Memory Address for test only the lower 13 are used (2^13 = 8192)
- reg [7:0] stat_reg;
- reg hibernate;
- SPI_FRAM_Module dut(.nCS(nCS), .SCK(SCK), .SI(SI), .SO(SO), .opcode(opcode), .addr(addr), .mem_data(mem_data),. stat_reg(stat_reg), .hibernate(hibernate));
-
-
- initial begin //values are set to startup values of FRAM
- nCS = 1'b1;
- SCK = 1'b0;
- end
-
- //generate 40MHz clock
- always @(nCS) begin
- while (nCS == 0) #12.5 SCK = ~SCK;
- if (nCS == 1) SCK = 0;
- end
-
- initial begin
- $dumpfile("dump.vcd");
- $dumpvars;
-
- SI = 0;
- nCS = 0;
-
- //TEST READ MEMORY
- // Sends 8'b00000011 as Read Opcode
- SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 1;
- #25; assert (opcode == 8'h03);
-
- //first byte (only the highest 4 bits are used) of 20-Bit address
- SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
-
- //second Byte of 20-Bit address
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- //third byte of address
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 1;
-
- //read one Byte (200clocks/25 clocks per bit = 8 bit)
- #25 assert (addr == 24'h000003); //check address
- //check for correct writing to SPI out of memory
- #25 assert (SO == 0);
- #25 assert (SO == 0);
- #25 assert (SO == 1);
- #25 assert (SO == 1);
- #25 assert (SO == 0);
- #25 assert (SO == 0);
- #25 assert (SO == 1);
- #25 assert (SO == 1);
-
- //Message is finished, so nCS is not active
- nCS = 1;
- #50 nCS = 0; //enable nCS after 50 clock cycles for next test
-
- //TEST WRITE MEMORY
- //send WREN opcode to set WEL bit
- SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 1;
- #25 SI = 0;
-
- //to set WEL-bit, nCS needs to be high (inactive)
- #25 nCS = 1;
- #25 assert (opcode == 8'h06); //check if the WREN-opcode was recognized
- #25 nCS = 0;
- assert (stat_reg[1] == 1'b1); //check if WEL-Bit is set
-
- //after stat_reg is set, the next opcode WRITE can be received
- SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 0;
- #25 assert (opcode == 8'h02);
- //the next 3 following Bytes are the address. the upper 4 Bits are cut off.
- //Highest Byte 1
- SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- //second address Byte
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- //third address Byte
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 0;
- #25 assert (addr == 24'h000002);
-
- //the following SI is written to the memory at the address "addr"
- //one Byte is written
- assert (mem_data[24'h000002] == 8'hFF); //check data at addr before to see difference after writing to it
- SI = 0;
- #25 SI = 1;
- #25 SI = 1;
- #25 SI = 1;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 0;
- //Message is finished, so nCS is not active
- #12.5 nCS = 1;
-
- #50 nCS = 0; //enable nCS after 50 clock cycles for next test
- assert (mem_data[24'h000002] == 8'h72); //check if the operation wrote the correct data to the correct address; 8'h72 is used because it is not symmetrical and the first and last bit are 0. Since the memory (see memory.txt) has 8'hFF written to all other bytes it is easily recognized if a 0 was accidentally written elsewhere.
- assert (mem_data[24'h000001] == 8'hFF);
-
- //test to see if write accidentally wrote in the next memory byte
- assert (mem_data[24'h000003] == 8'h33);
-
-
- //test opcode read status register
- SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 0;
- #25 SI = 1;
-
- #25 assert (opcode == 8'h05);
-
- //Test correct writing to SPI of status register (stat_reg = 8'h20)
- #25 assert (SO == 0);
- #25 assert (SO == 0);
- #25 assert (SO == 1);
- #25 assert (SO == 0);
- #25 assert (SO == 0);
- #25 assert (SO == 0);
- #25 assert (SO == 0);
- #25 assert (SO == 0);
-
-
- assert (stat_reg == 8'h20);
-
- //Message is finished, so nCS is not active
- #50 nCS = 1;
-
- #25 nCS = 0; //enable nCS and SCK after 50 clock cycles for next test
-
-
-
- //TEST HIBERNATE MODE
- //send opcode
- SI = 1;
- #25 SI = 0;
- #25 SI = 1;
- #25 SI = 1;
- #25 SI = 1;
- #25 SI = 0;
- #25 SI = 0;
- #25 SI = 1;
- #25 assert (opcode == 8'hb9);
-
-
- //Message is finished, so nCS is not active
- //hibernate is set on the rising edge of nCS and reset at the falling edge of nCS
- nCS = 1;
- #25 assert (hibernate == 1);
- #500 nCS = 0; //enable nCS and SCK after 50 clock cycles for next test
- #25 assert (hibernate == 0);
-
- end
- endmodule
|