`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