200 lines
5.7 KiB
Systemverilog
200 lines
5.7 KiB
Systemverilog
![]() |
`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
|