diff --git a/FRAM Controller/FRAM_Controller.sv b/FRAM Controller/FRAM_Controller.sv new file mode 100644 index 0000000..2009257 --- /dev/null +++ b/FRAM Controller/FRAM_Controller.sv @@ -0,0 +1,199 @@ +`include "SPI.sv" + +module FRAM( + input i_clk, //Module (Module CLock = SPI Clock) + input i_nreset, + + input logic [19:0] i_adr, //Memorycell adress in FRAM + input logic [7:0] i_data, //data to write + output logic [7:0] o_data, //data to read + + input logic i_rw, //Read = 1, Write = 0 + input logic i_status, //If 1 Read Staut register + input logic i_hbn, //If 1 FRAM will enter Hibernation Mode + input logic i_cready, //Starts transmission + output logic o_busy, //Indicates FRAM Busy + + // SPI Interface + output o_SPI_Clk, + input i_SPI_MISO, + output o_SPI_MOSI, + output o_SPI_CS_n + +); + + + //FRAM SPI OP Codes + + //Write Enable Control + localparam WREN = 8'h06; //Set Write enable latch + localparam WRDI = 8'h04; //Reset write enable latch + //Register Access + localparam RDSR = 8'h05; //Read Status Register + localparam WRSR = 8'h01; //Write Status Register + //Memory Write + localparam WRITE = 8'h02; //Write Memory Data + //Memory Read + localparam READ = 8'h03; //Read Memory Data + localparam FSTRT = 8'h0B; //Fast read memory Data + //Special Sector Memory Access + localparam SSWR = 8'h42; //Spcial Sector Write + localparam SSRD = 8'h4B; //Special Sector Read + //Identification and serial Number + localparam RDID = 8'h9F; //Read Device ID + localparam RUID = 8'h4C; //Read Unique ID + localparam WRSN = 8'hC2; //Write Serial Number + localparam RDSN = 8'hC3; //Read Serial Number + //Low Power Modes + localparam DPD = 8'hBA; // Enter Deep Power-Down + localparam HBN = 8'hB9; // Enter Hibernate Mode + //end FRAM SPI OP Codes + + //Controller Specific + logic [3:0] state; + + + // SPI Specific + parameter SPI_MODE = 0; // CPOL = 0, CPHA = 0 + parameter CLKS_PER_HALF_BIT = 2; // 25MHz + parameter MAX_BYTES_PER_CS = 5; // 5 bytes max per chip select cycle + parameter CS_INACTIVE_CLKS = 1; // Adds delay (1clk) between cycles + + + logic [7:0] r_Master_TX_Byte = 0; + logic r_Master_TX_DV = 1'b0; + logic w_Master_TX_Ready; + logic w_Master_RX_DV; + logic [7:0] w_Master_RX_Byte; + logic [$clog2(MAX_BYTES_PER_CS+1)-1:0] w_Master_RX_Count, r_Master_TX_Count = 3'h1; //Standard 1 Byte pro CS Cycle + + + + SPI_Master_With_Single_CS + #(.SPI_MODE(SPI_MODE), //SPI Mode 0-3 + .CLKS_PER_HALF_BIT(CLKS_PER_HALF_BIT), //sets Frequency of SPI_CLK + .MAX_BYTES_PER_CS(MAX_BYTES_PER_CS), //Maximum Bytes per CS Cycle + .CS_INACTIVE_CLKS(CS_INACTIVE_CLKS) //Amount of Time holding CS Low befor next command + ) SPI + ( + // Control/Data Signals, + .i_Rst_L(i_nreset), // FPGA Reset + .i_Clk(i_clk), // FPGA Clock + + // TX (MOSI) Signals + .i_TX_Count(r_Master_TX_Count), // Number of bytes per CS + .i_TX_Byte(r_Master_TX_Byte), // Byte to transmit on MOSI + .i_TX_DV(r_Master_TX_DV), // Data Valid Pulse with i_TX_Byte + .o_TX_Ready(w_Master_TX_Ready), // Transmit Ready for Byte + + // RX (MISO) Signals + .o_RX_Count(w_Master_RX_Count), // Index of RX'd byte + .o_RX_DV(w_Master_RX_DV), // Data Valid pulse (1 clock cycle) + .o_RX_Byte(w_Master_RX_Byte), // Byte received on MISO + + // SPI Interface + .o_SPI_Clk(o_SPI_Clk), + .i_SPI_MISO(i_SPI_MISO), + .o_SPI_MOSI(o_SPI_MOSI), + .o_SPI_CS_n(o_SPI_CS_n) + ); + + //end SPI Specific + + + task SPI_SendByte(input [7:0] data); + @(posedge i_clk); + r_Master_TX_Byte <= data; + r_Master_TX_DV <= 1'b1; + @(posedge i_clk); + r_Master_TX_DV <= 1'b0; + @(posedge i_clk); + @(posedge w_Master_TX_Ready); + endtask //end SPI_SendByte + + //FRAM Tasks + task FRAM_Write(input [19:0] adr, input [7:0] data); //vgl. Fig.11 + + logic [7:0] value; + value <= 8'h0; + + //Set Write Enable + r_Master_TX_Count <= 3'b1; //1Byte Transaction + SPI_SendByte(WREN); + + //Write to fram + r_Master_TX_Count <= 3'h5; //5 Byte Transaction + SPI_SendByte(WRITE); //OPCode + SPI_SendByte({4'hF,adr[19:16]}); //Adress [23-16] + SPI_SendByte(adr[15:8]); //Adress [15-8] + SPI_SendByte(adr[7:0]); //Adress [7-0] + SPI_SendByte(data); //Data [7:0] + + //Reset Write Disable and Verify + do begin + r_Master_TX_Count <= 3'b1; //1Byte Transaction + SPI_SendByte(WRDI); //Set Write Disable + + FRAM_Read_Status(value); //Lese Status Register + end while(((value & 8'h2) >> 1) != 0); + + + endtask //end FRAM_Write + + task FRAM_Read(input [19:0] adr, output [7:0] data); //vgl. Fig12 + r_Master_TX_Count <= 3'h5; //5 Byte Transaction + SPI_SendByte(READ); //Opcode + SPI_SendByte({4'hF,adr[19:16]}); //Adress [23-16] + SPI_SendByte(adr[15:8]); //Adress [15-8] + SPI_SendByte(adr[7:0]); //Adress [7-0] + + SPI_SendByte(8'hAA); //Dummy Bits, read byte in w_Master_RX_Byte + data = w_Master_RX_Byte; + + endtask //end FRAM_READ + + task FRAM_Read_Status(output [7:0] data); //vgl. Fig9 + r_Master_TX_Count <= 3'h2; //2 Byte Transaction + SPI_SendByte(RDSR); //OpCode + SPI_SendByte(8'hFD); //Dummy Bits, read byte in w_Master_RX_Byte + data = w_Master_RX_Byte; + endtask //FRAM_Read_Status + + task FRAM_Hibernation(); //vgl. Fig22 + r_Master_TX_Count <= 3'h1; //1 Byte Transaction + SPI_SendByte(HBN); + endtask //FRAM_Hibernation + + + //end FRAM Tasks + + + always @(posedge i_clk or negedge i_nreset) begin + + state[0] = i_cready; + state[1] = i_hbn; + state[2] = i_status; + state[3] = i_rw; + + if(~i_nreset) begin //Modul Reset + o_data <= 8'h00; + end //end if + + if(w_Master_TX_Ready) begin + case(state) inside + 4'b??11: FRAM_Hibernation(); + 4'b?101: FRAM_Read_Status(o_data); + 4'b1001: FRAM_Read(i_adr, o_data); + 4'b0001: FRAM_Write(i_adr, i_data); + + default:; + endcase //endcase + end //endif + + end //end always + + + assign o_busy = w_Master_TX_Ready; + + +endmodule diff --git a/FRAM Controller/SPI FRAM Controller.pdf b/FRAM Controller/SPI FRAM Controller.pdf new file mode 100644 index 0000000..0ec04c0 Binary files /dev/null and b/FRAM Controller/SPI FRAM Controller.pdf differ diff --git a/FRAM Controller/SPI_Master.sv b/FRAM Controller/SPI_Master.sv new file mode 100644 index 0000000..e9fe26a --- /dev/null +++ b/FRAM Controller/SPI_Master.sv @@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////////// +//Source: https://github.com/nandland/spi-master/tree/master/Verilog/source +//Description: SPI (Serial Peripheral Interface) Master +// With single chip-select (AKA Slave Select) capability +// +// Supports arbitrary length byte transfers. +// +// Instantiates a SPI Master and adds single CS. +// If multiple CS signals are needed, will need to use different +// module, OR multiplex the CS from this at a higher level. +// +// Note: i_Clk must be at least 2x faster than i_SPI_Clk +// +// Parameters: SPI_MODE, can be 0, 1, 2, or 3. See above. +// Can be configured in one of 4 modes: +// Mode | Clock Polarity (CPOL/CKP) | Clock Phase (CPHA) +// 0 | 0 | 0 +// 1 | 0 | 1 +// 2 | 1 | 0 +// 3 | 1 | 1 +// +// CLKS_PER_HALF_BIT - Sets frequency of o_SPI_Clk. o_SPI_Clk is +// derived from i_Clk. Set to integer number of clocks for each +// half-bit of SPI data. E.g. 100 MHz i_Clk, CLKS_PER_HALF_BIT = 2 +// would create o_SPI_CLK of 25 MHz. Must be >= 2 +// +// MAX_BYTES_PER_CS - Set to the maximum number of bytes that +// will be sent during a single CS-low pulse. +// +// CS_INACTIVE_CLKS - Sets the amount of time in clock cycles to +// hold the state of Chip-Selct high (inactive) before next +// command is allowed on the line. Useful if chip requires some +// time when CS is high between trasnfers. +/////////////////////////////////////////////////////////////////////////////// +`include "iSPI.sv" + + +module SPI_Master_With_Single_CS + #(parameter SPI_MODE = 0, + parameter CLKS_PER_HALF_BIT = 2, + parameter MAX_BYTES_PER_CS = 1, + parameter CS_INACTIVE_CLKS = 1) + ( + // Control/Data Signals, + input i_Rst_L, // FPGA Reset + input i_Clk, // FPGA Clock + + // TX (MOSI) Signals + input [$clog2(MAX_BYTES_PER_CS+1)-1:0] i_TX_Count, // # bytes per CS low + input [7:0] i_TX_Byte, // Byte to transmit on MOSI + input i_TX_DV, // Data Valid Pulse with i_TX_Byte + output o_TX_Ready, // Transmit Ready for next byte + + // RX (MISO) Signals + output reg [$clog2(MAX_BYTES_PER_CS+1)-1:0] o_RX_Count, // Index RX byte + output o_RX_DV, // Data Valid pulse (1 clock cycle) + output [7:0] o_RX_Byte, // Byte received on MISO + + // SPI Interface + output o_SPI_Clk, + input i_SPI_MISO, + output o_SPI_MOSI, + output o_SPI_CS_n + ); + + localparam IDLE = 2'b00; + localparam TRANSFER = 2'b01; + localparam CS_INACTIVE = 2'b10; + + reg [1:0] r_SM_CS; + reg r_CS_n; + reg [$clog2(CS_INACTIVE_CLKS)-1:0] r_CS_Inactive_Count; + reg [$clog2(MAX_BYTES_PER_CS+1)-1:0] r_TX_Count; + wire w_Master_Ready; + + // Instantiate Master + SPI_Master + #(.SPI_MODE(SPI_MODE), + .CLKS_PER_HALF_BIT(CLKS_PER_HALF_BIT) + ) SPI_Master_Inst + ( + // Control/Data Signals, + .i_Rst_L(i_Rst_L), // FPGA Reset + .i_Clk(i_Clk), // FPGA Clock + + // TX (MOSI) Signals + .i_TX_Byte(i_TX_Byte), // Byte to transmit + .i_TX_DV(i_TX_DV), // Data Valid Pulse + .o_TX_Ready(w_Master_Ready), // Transmit Ready for Byte + + // RX (MISO) Signals + .o_RX_DV(o_RX_DV), // Data Valid pulse (1 clock cycle) + .o_RX_Byte(o_RX_Byte), // Byte received on MISO + + // SPI Interface + .o_SPI_Clk(o_SPI_Clk), + .i_SPI_MISO(i_SPI_MISO), + .o_SPI_MOSI(o_SPI_MOSI) + ); + + + // Purpose: Control CS line using State Machine + always @(posedge i_Clk or negedge i_Rst_L) + begin + if (~i_Rst_L) + begin + r_SM_CS <= IDLE; + r_CS_n <= 1'b1; // Resets to high + r_TX_Count <= 0; + r_CS_Inactive_Count <= CS_INACTIVE_CLKS; + end + else + begin + + case (r_SM_CS) + IDLE: + begin + if (r_CS_n & i_TX_DV) // Start of transmission + begin + r_TX_Count <= i_TX_Count - 1; // Register TX Count + r_CS_n <= 1'b0; // Drive CS low + r_SM_CS <= TRANSFER; // Transfer bytes + end + end + + TRANSFER: + begin + // Wait until SPI is done transferring do next thing + if (w_Master_Ready) + begin + if (r_TX_Count > 0) + begin + if (i_TX_DV) + begin + r_TX_Count <= r_TX_Count - 1; + end + end + else + begin + r_CS_n <= 1'b1; // we done, so set CS high + r_CS_Inactive_Count <= CS_INACTIVE_CLKS; + r_SM_CS <= CS_INACTIVE; + end // else: !if(r_TX_Count > 0) + end // if (w_Master_Ready) + end // case: TRANSFER + + CS_INACTIVE: + begin + if (r_CS_Inactive_Count > 0) + begin + r_CS_Inactive_Count <= r_CS_Inactive_Count - 1'b1; + end + else + begin + r_SM_CS <= IDLE; + end + end + + default: + begin + r_CS_n <= 1'b1; // we done, so set CS high + r_SM_CS <= IDLE; + end + endcase // case (r_SM_CS) + end + end // always @ (posedge i_Clk or negedge i_Rst_L) + + + // Purpose: Keep track of RX_Count + always @(posedge i_Clk) + begin + begin + if (r_CS_n) + begin + o_RX_Count <= 0; + end + else if (o_RX_DV) + begin + o_RX_Count <= o_RX_Count + 1'b1; + end + end + end + + assign o_SPI_CS_n = r_CS_n; + + assign o_TX_Ready = ((r_SM_CS == IDLE) | (r_SM_CS == TRANSFER && w_Master_Ready == 1'b1 && r_TX_Count > 0)) & ~i_TX_DV; + +endmodule // SPI_Master_With_Single_CS \ No newline at end of file diff --git a/FRAM Controller/SPI_Master_Control.sv b/FRAM Controller/SPI_Master_Control.sv new file mode 100644 index 0000000..87840ab --- /dev/null +++ b/FRAM Controller/SPI_Master_Control.sv @@ -0,0 +1,240 @@ +/////////////////////////////////////////////////////////////////////////////// +//Source: https://github.com/nandland/spi-master/tree/master/Verilog/source +// Description: SPI (Serial Peripheral Interface) Master +// Creates master based on input configuration. +// Sends a byte one bit at a time on MOSI +// Will also receive byte data one bit at a time on MISO. +// Any data on input byte will be shipped out on MOSI. +// +// To kick-off transaction, user must pulse i_TX_DV. +// This module supports multi-byte transmissions by pulsing +// i_TX_DV and loading up i_TX_Byte when o_TX_Ready is high. +// +// This module is only responsible for controlling Clk, MOSI, +// and MISO. If the SPI peripheral requires a chip-select, +// this must be done at a higher level. +// +// Note: i_Clk must be at least 2x faster than i_SPI_Clk +// +// Parameters: SPI_MODE, can be 0, 1, 2, or 3. See above. +// Can be configured in one of 4 modes: +// Mode | Clock Polarity (CPOL/CKP) | Clock Phase (CPHA) +// 0 | 0 | 0 +// 1 | 0 | 1 +// 2 | 1 | 0 +// 3 | 1 | 1 +// More: https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Mode_numbers +// CLKS_PER_HALF_BIT - Sets frequency of o_SPI_Clk. o_SPI_Clk is +// derived from i_Clk. Set to integer number of clocks for each +// half-bit of SPI data. E.g. 100 MHz i_Clk, CLKS_PER_HALF_BIT = 2 +// would create o_SPI_CLK of 25 MHz. Must be >= 2 +// +/////////////////////////////////////////////////////////////////////////////// + +module SPI_Master + #(parameter SPI_MODE = 0, + parameter CLKS_PER_HALF_BIT = 2) + ( + // Control/Data Signals, + input i_Rst_L, // FPGA Reset + input i_Clk, // FPGA Clock + + // TX (MOSI) Signals + input [7:0] i_TX_Byte, // Byte to transmit on MOSI + input i_TX_DV, // Data Valid Pulse with i_TX_Byte + output reg o_TX_Ready, // Transmit Ready for next byte + + // RX (MISO) Signals + output reg o_RX_DV, // Data Valid pulse (1 clock cycle) + output reg [7:0] o_RX_Byte, // Byte received on MISO + + // SPI Interface + output reg o_SPI_Clk, + input i_SPI_MISO, + output reg o_SPI_MOSI + ); + + // SPI Interface (All Runs at SPI Clock Domain) + wire w_CPOL; // Clock polarity + wire w_CPHA; // Clock phase + + reg [$clog2(CLKS_PER_HALF_BIT*2)-1:0] r_SPI_Clk_Count; + reg r_SPI_Clk; + reg [4:0] r_SPI_Clk_Edges; + reg r_Leading_Edge; + reg r_Trailing_Edge; + reg r_TX_DV; + reg [7:0] r_TX_Byte; + + reg [2:0] r_RX_Bit_Count; + reg [2:0] r_TX_Bit_Count; + + // CPOL: Clock Polarity + // CPOL=0 means clock idles at 0, leading edge is rising edge. + // CPOL=1 means clock idles at 1, leading edge is falling edge. + assign w_CPOL = (SPI_MODE == 2) | (SPI_MODE == 3); + + // CPHA: Clock Phase + // CPHA=0 means the "out" side changes the data on trailing edge of clock + // the "in" side captures data on leading edge of clock + // CPHA=1 means the "out" side changes the data on leading edge of clock + // the "in" side captures data on the trailing edge of clock + assign w_CPHA = (SPI_MODE == 1) | (SPI_MODE == 3); + + + + // Purpose: Generate SPI Clock correct number of times when DV pulse comes + always @(posedge i_Clk or negedge i_Rst_L) + begin + if (~i_Rst_L) + begin + o_TX_Ready <= 1'b0; + r_SPI_Clk_Edges <= 0; + r_Leading_Edge <= 1'b0; + r_Trailing_Edge <= 1'b0; + r_SPI_Clk <= w_CPOL; // assign default state to idle state + r_SPI_Clk_Count <= 0; + end + else + begin + + // Default assignments + r_Leading_Edge <= 1'b0; + r_Trailing_Edge <= 1'b0; + + if (i_TX_DV) + begin + o_TX_Ready <= 1'b0; + r_SPI_Clk_Edges <= 16; // Total # edges in one byte ALWAYS 16 + end + else if (r_SPI_Clk_Edges > 0) + begin + o_TX_Ready <= 1'b0; + + if (r_SPI_Clk_Count == CLKS_PER_HALF_BIT*2-1) + begin + r_SPI_Clk_Edges <= r_SPI_Clk_Edges - 1; + r_Trailing_Edge <= 1'b1; + r_SPI_Clk_Count <= 0; + r_SPI_Clk <= ~r_SPI_Clk; + end + else if (r_SPI_Clk_Count == CLKS_PER_HALF_BIT-1) + begin + r_SPI_Clk_Edges <= r_SPI_Clk_Edges - 1; + r_Leading_Edge <= 1'b1; + r_SPI_Clk_Count <= r_SPI_Clk_Count + 1; + r_SPI_Clk <= ~r_SPI_Clk; + end + else + begin + r_SPI_Clk_Count <= r_SPI_Clk_Count + 1; + end + end + else + begin + o_TX_Ready <= 1'b1; + end + + + end // else: !if(~i_Rst_L) + end // always @ (posedge i_Clk or negedge i_Rst_L) + + + // Purpose: Register i_TX_Byte when Data Valid is pulsed. + // Keeps local storage of byte in case higher level module changes the data + always @(posedge i_Clk or negedge i_Rst_L) + begin + if (~i_Rst_L) + begin + r_TX_Byte <= 8'h00; + r_TX_DV <= 1'b0; + end + else + begin + r_TX_DV <= i_TX_DV; // 1 clock cycle delay + if (i_TX_DV) + begin + r_TX_Byte <= i_TX_Byte; + end + end // else: !if(~i_Rst_L) + end // always @ (posedge i_Clk or negedge i_Rst_L) + + + // Purpose: Generate MOSI data + // Works with both CPHA=0 and CPHA=1 + always @(posedge i_Clk or negedge i_Rst_L) + begin + if (~i_Rst_L) + begin + o_SPI_MOSI <= 1'b0; + r_TX_Bit_Count <= 3'b111; // send MSb first + end + else + begin + // If ready is high, reset bit counts to default + if (o_TX_Ready) + begin + r_TX_Bit_Count <= 3'b111; + end + // Catch the case where we start transaction and CPHA = 0 + else if (r_TX_DV & ~w_CPHA) + begin + o_SPI_MOSI <= r_TX_Byte[3'b111]; + r_TX_Bit_Count <= 3'b110; + end + else if ((r_Leading_Edge & w_CPHA) | (r_Trailing_Edge & ~w_CPHA)) + begin + r_TX_Bit_Count <= r_TX_Bit_Count - 1; + o_SPI_MOSI <= r_TX_Byte[r_TX_Bit_Count]; + end + end + end + + + // Purpose: Read in MISO data. + always @(posedge i_Clk or negedge i_Rst_L) + begin + if (~i_Rst_L) + begin + o_RX_Byte <= 8'h00; + o_RX_DV <= 1'b0; + r_RX_Bit_Count <= 3'b111; + end + else + begin + + // Default Assignments + o_RX_DV <= 1'b0; + + if (o_TX_Ready) // Check if ready is high, if so reset bit count to default + begin + r_RX_Bit_Count <= 3'b111; + end + else if ((r_Leading_Edge & ~w_CPHA) | (r_Trailing_Edge & w_CPHA)) + begin + o_RX_Byte[r_RX_Bit_Count] <= i_SPI_MISO; // Sample data + r_RX_Bit_Count <= r_RX_Bit_Count - 1; + if (r_RX_Bit_Count == 3'b000) + begin + o_RX_DV <= 1'b1; // Byte done, pulse Data Valid + end + end + end + end + + + // Purpose: Add clock delay to signals for alignment. + always @(posedge i_Clk or negedge i_Rst_L) + begin + if (~i_Rst_L) + begin + o_SPI_Clk <= w_CPOL; + end + else + begin + o_SPI_Clk <= r_SPI_Clk; + end // else: !if(~i_Rst_L) + end // always @ (posedge i_Clk or negedge i_Rst_L) + + +endmodule // SPI_Master \ No newline at end of file diff --git a/FRAM Controller/testbench.sv b/FRAM Controller/testbench.sv new file mode 100644 index 0000000..3b2a5fa --- /dev/null +++ b/FRAM Controller/testbench.sv @@ -0,0 +1,168 @@ +module testbench(); + + logic clk; + logic nReset; + + logic [19:0] FRAM_Adr; + logic [7:0] FRAM_DATA_OUT; + logic [7:0] FRAM_DATA_IN; + logic FRAM_RW; + logic FRAM_RSTATUS; + logic FRAM_hbn; + logic FRAM_go; + logic FRAM_busy; + + logic SPI_CLK; + logic SPI_MISO; + logic SPI_MOSI; + logic SPI_CS; + + logic [2:0]test; + logic test_running; + logic starttesting; + + localparam TESTS_cnt = 5; + + initial begin + // Required for EDA Playground + $dumpfile("dump.vcd"); + $dumpvars; + + clk = 1'h0; + nReset = 1'h0; + + FRAM_Adr <= 20'h0; + FRAM_DATA_IN <= 8'h0; + FRAM_RW = 0; + FRAM_RSTATUS = 0; + FRAM_hbn = 0; + FRAM_go = 0; + + test <= 2'h0; + + repeat(10) @(posedge clk); + nReset = 1'h1; + + starttesting <= 1'h1; + test_running <= 1'h0; + + end //initial end + + + + // Clock Generation: + always #(5) clk = ~clk; //clk 100MHz + // end Clock Generation + + + always @ (posedge starttesting or posedge FRAM_busy) begin + + repeat(10) @(posedge clk); + if(test_running == 1'h0 & FRAM_busy == 1'h1) begin + + if(test == TESTS_cnt+1) begin + test_running <= 1'h0; + $display("Tests Finished"); + $finish; + end + + case(test) inside + 3'b000: begin Test1(); test <= test + 1'h1; end + 3'b001: begin Test2(); test <= test + 1'h1; end + 3'b010: begin Test3(); test <= test + 1'h1; end + 3'b011: begin Test4(); test <= test + 1'h1; end + + endcase + end // endif + end // end always + + + + + task Test1(); + test_running <= 1'h1; + $display("DEBUG: %0tns: Test_1_Hibernation",$realtime); + FRAM_hbn <= 1'h1; //Enter Hibernation + FRAM_go <= 1'h1; + #10; + FRAM_hbn <= 1'h0; //Reset Hibernation Flag + FRAM_go <= 1'h0; + $display("DEBUG: %0tns: Test_1_Hibernation__-END",$realtime); + test_running <= 1'h0; + endtask + + task Test2(); + test_running <= 1'h1; + $display("DEBUG: %0tns: Test_2_ReadStatus",$realtime); + FRAM_RSTATUS <= 1'h1; //Read Status + FRAM_go <= 1'h1; //Go + #10; + FRAM_RSTATUS <= 1'h0; //Read Status + FRAM_go <= 1'h0; //reset Go + $display("DEBUG: %0tns: Test_2_ReadStatus__-END",$realtime); + test_running <= 1'h0; + endtask + + task Test3(); + test_running <= 1'h1; + $display("DEBUG: %0tns: Test_3_FRAM_WRITE",$realtime); + FRAM_Adr <= 20'h8FFF1; //Load 8FFF1 as adress + FRAM_DATA_IN <= 8'hAA; //Load AA as Data to Write into FRAM + FRAM_RW <= 1'h0; //Write Operation + FRAM_go <= 1'h1; //Go + #10; + FRAM_go <= 1'h0; //resetGo + $display("DEBUG: %0tns: Test_3_FRAM_WRITE__-END",$realtime); + test_running <= 1'h0; + endtask + + task Test4(); + test_running <= 1'h1; + $display("DEBUG: %0tns: Test_4_FRAM_READ",$realtime); + FRAM_Adr <= 20'h8FFF1; //Load 8FFF1 as adress + FRAM_RW <= 1'h1; //Read + FRAM_go <= 1'h1; //Go + #10; + FRAM_go <= 1'h0; //resetGo + FRAM_RW <= 1'h0; //Read + $display("DEBUG: %0tns: Test_4_FRAM_READ__-END",$realtime); + test_running <= 1'h0; + endtask + + + + FRAM FRAM_ut( + .i_clk(clk), + .i_nreset(nReset), + .i_adr(FRAM_Adr), + .i_data(FRAM_DATA_IN), + .o_data(FRAM_DATA_OUT), + .i_rw(FRAM_RW), + .i_status(FRAM_RSTATUS), + .i_hbn(FRAM_hbn), + .i_cready(FRAM_go), + .o_busy(FRAM_busy), + + .o_SPI_Clk(SPI_CLK), + .i_SPI_MISO(SPI_MOSI), // !!! only for Testing!!! + .o_SPI_MOSI(SPI_MOSI), // + .o_SPI_CS_n(SPI_CS) + ); + + + + + + + + + + + +endmodule + + + + + + \ No newline at end of file