Dateien hochladen nach „“
This commit is contained in:
parent
fec9cd1ae0
commit
f691d1318a
BIN
FRAM_Speicher-Modell.pdf
Normal file
BIN
FRAM_Speicher-Modell.pdf
Normal file
Binary file not shown.
BIN
Projekt_2022.docx
Normal file
BIN
Projekt_2022.docx
Normal file
Binary file not shown.
12520
SPI FRAM Controller.pdf
Normal file
12520
SPI FRAM Controller.pdf
Normal file
File diff suppressed because it is too large
Load Diff
180
SPI_FRAM_Module.sv
Normal file
180
SPI_FRAM_Module.sv
Normal file
@ -0,0 +1,180 @@
|
||||
module SPI_FRAM_Module(
|
||||
input wire SI,
|
||||
output wire SO,
|
||||
input reg SCK,
|
||||
input reg nCS,
|
||||
output reg [7:0] opcode, //contains the command which controls the FRAM
|
||||
output reg [23:0] addr, //contains current address that the memory is reading/writing
|
||||
reg [7:0] mem_data [1023:0], //contains the memory data
|
||||
reg [7:0] stat_reg, //stat_reg Bit 0 is 1 while waking up from Hibernate
|
||||
reg hibernate); //if true, memory is in hibernation
|
||||
|
||||
reg [2:0] bitcnt_rcv; //counts the bits of the current byte when reading from SPI
|
||||
reg [2:0] bitcnt_snd; //counts sent bits for the current sent byte when writing to SPI
|
||||
reg [2:0] bitcnt_mem_write; //counts bits written to memory for the current received byte
|
||||
reg byte_received; //gets high when a full byte is received
|
||||
reg [7:0] byte_data_received; //contains the data of last received byte
|
||||
reg [3:0] byte_count; //counts the bytes of one message; is reset when a new message starts
|
||||
reg [7:0] byte_data_sent; //contains the sent byte after transmission
|
||||
reg send_data; //is set by opcode commands Read status register and Read memory when writing to SPI
|
||||
reg write_to_memory; ////is set by opcode WRITE, when high, incoming Bits from SI are written to the memory at a specific address.
|
||||
integer i; //countdown variable for status register read
|
||||
|
||||
|
||||
initial begin //values are set to startup values of FRAM
|
||||
opcode = 8'h00;
|
||||
stat_reg = 8'b00100000;
|
||||
addr = 24'h000000;
|
||||
byte_count = 4'b0000;
|
||||
byte_data_sent = 8'h00;
|
||||
bitcnt_rcv = 3'b000;
|
||||
bitcnt_snd = 3'b111;
|
||||
bitcnt_mem_write = 3'b111;
|
||||
byte_received = 1'b0;
|
||||
byte_data_received = 8'b00000000;
|
||||
send_data = 0;
|
||||
write_to_memory = 0;
|
||||
i = 8;
|
||||
hibernate = 0;
|
||||
$readmemh("memory.txt", mem_data); //initializes the memory with the contents of memory.txt
|
||||
end
|
||||
|
||||
//receive incoming Bits and organize them bytewise
|
||||
always @(posedge SCK) begin
|
||||
if (bitcnt_rcv == 3'b111) begin
|
||||
byte_count <= byte_count + 4'b0001;
|
||||
end
|
||||
bitcnt_rcv <= bitcnt_rcv + 3'b001;
|
||||
byte_data_received <= {byte_data_received[6:0], SI};
|
||||
|
||||
//when opcode WRÍTE is executed, the incoming bytes are written to memory
|
||||
if (write_to_memory == 1 && nCS == 0) begin
|
||||
mem_data[addr][bitcnt_mem_write+3'b001] = byte_data_received[0];
|
||||
|
||||
if(bitcnt_mem_write == 3'b000) begin
|
||||
addr <= addr + 1;
|
||||
bitcnt_mem_write <= 3'b111;
|
||||
end
|
||||
bitcnt_mem_write <= bitcnt_mem_write - 1;
|
||||
end
|
||||
end
|
||||
always @(posedge SCK) byte_received <= (nCS == 0) && (bitcnt_rcv==3'b111);
|
||||
|
||||
//TRANSMISSION
|
||||
//Read out memory and write to SPI, starts at addr
|
||||
always @(negedge SCK) begin
|
||||
if(send_data == 1 && nCS == 0)
|
||||
begin
|
||||
byte_data_sent <= {byte_data_sent[6:0], mem_data[addr][bitcnt_snd]};
|
||||
bitcnt_snd <= bitcnt_snd - 1;
|
||||
if (bitcnt_snd == 3'b000) begin
|
||||
addr <= addr + 1;
|
||||
bitcnt_snd <= 3'b111;
|
||||
end
|
||||
end
|
||||
//write status register to SO when opcode RDSR is sent
|
||||
else if (opcode == 8'h05 && nCS == 0 && i > 0) begin
|
||||
byte_data_sent <= {byte_data_sent[6:0], stat_reg[i-1]};
|
||||
i = i - 1;
|
||||
end
|
||||
end
|
||||
assign SO = byte_data_sent[0]; // MSB of the transmission is the lsb of byte_data_sent
|
||||
|
||||
|
||||
|
||||
//the following block resets counters when a message has finished
|
||||
always @ (posedge nCS) begin
|
||||
if (opcode == 8'h06) begin //When WLEN opcode is executed, nCS needs to be reset.
|
||||
//Since the message is not finished, no counters should be reset when executing WLEN
|
||||
end
|
||||
else if (opcode == 8'hb9 && nCS == 1) hibernate = 1; //When hibernation opcode 8'hb9 is sent, the device goes into hibernation
|
||||
else begin
|
||||
byte_count = 8'h00;
|
||||
bitcnt_rcv = 3'b000;
|
||||
bitcnt_snd = 3'b111;
|
||||
bitcnt_mem_write = 3'b111;
|
||||
byte_data_received = 8'h00;
|
||||
end
|
||||
send_data = 0; //disables sending data
|
||||
write_to_memory = 0; // disables writing to memory
|
||||
stat_reg[1] = 0; //reset WEL when writing to memory has finished
|
||||
end
|
||||
|
||||
//reset hibernate
|
||||
always @ (negedge nCS) hibernate = 0;
|
||||
//when a byte is received the FRAM-model reacts dependent on the number of bytes received in the current nCS low state, i. e. in one message.
|
||||
|
||||
always @ (posedge byte_received) begin
|
||||
case (byte_count)
|
||||
//Byte 1 of message
|
||||
4'h1: begin //counting starts at 1, not 0.
|
||||
case (byte_data_received)
|
||||
8'h03: //READ Op-code
|
||||
opcode = 8'h03;
|
||||
8'h06: begin //WREN Op-Code
|
||||
opcode = 8'h06;
|
||||
#25; //wait one clock for nCS to get low
|
||||
if (nCS == 1) stat_reg [1] = 1; //Set WEL Bit in Status Register after one clock cycle
|
||||
end
|
||||
//READ STATUS REGISTER Op-Code
|
||||
8'h05: opcode = 8'h05;
|
||||
//HIBERNATE Op-Code
|
||||
8'hb9: begin
|
||||
opcode = 8'hb9;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
//Byte 2 of message
|
||||
4'h2: begin
|
||||
case (byte_data_received)
|
||||
//WRITE
|
||||
8'h02: //WRITE Op-code, only if WREN op-code was executed, WRITE Op-code is permitted.
|
||||
if (opcode == 8'h06) opcode = 8'h02;
|
||||
default:
|
||||
//READ - get highest address byte
|
||||
if (opcode == 8'h03) //upper four bits are not used and are always 0
|
||||
//the address is shifted in from right to left. Byte_data_received is the highest byte of the address
|
||||
addr <= {4'b0000, 12'h000, byte_data_received};
|
||||
endcase
|
||||
end
|
||||
//Byte 3 of message
|
||||
4'h3: begin
|
||||
case (byte_data_received)
|
||||
default:
|
||||
//READ - get middle address byte
|
||||
if (opcode == 8'h03) //if opcode is read, the byte_data_received
|
||||
//is the next byte of the address, followed by 1 byte
|
||||
addr <= {4'b0000, 4'b0000, addr[7:0], byte_data_received};
|
||||
//WRITE - get highest address byte
|
||||
else if (opcode == 8'h02 && stat_reg[1] == 1'b1)
|
||||
addr <= {4'b0000, 12'h000, byte_data_received};
|
||||
endcase
|
||||
end
|
||||
//Byte 4 of message
|
||||
4'h4: begin
|
||||
case (byte_data_received)
|
||||
default:
|
||||
//READ - get the lowest byte of the address
|
||||
if (opcode == 8'h03) begin
|
||||
addr <= {addr[15:0], byte_data_received};
|
||||
send_data = 1; //sets the flag which starts sending every bit out of SO at memory address "addr".
|
||||
end
|
||||
//WRITE - get middle address byte
|
||||
else if (opcode == 8'h02 && stat_reg[1] == 1'b1)
|
||||
addr <= {4'b000, 4'b0000, addr[7:0], byte_data_received};
|
||||
endcase
|
||||
end
|
||||
//Byte 5 of message
|
||||
4'h5: begin
|
||||
case (byte_data_received)
|
||||
default:
|
||||
//WRITE - get lowest address byte and enable write_to_memory, the following bytes are data.
|
||||
if (opcode == 8'h02 && stat_reg[1] == 1'b1) begin
|
||||
addr <= {addr[15:0], byte_data_received};
|
||||
write_to_memory = 1; //set write to memory and wait one clock
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
1024
memory.txt
Normal file
1024
memory.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user