You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SPI_FRAM_Module.sv 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. module SPI_FRAM_Module(
  2. input wire SI,
  3. output wire SO,
  4. input reg SCK,
  5. input reg nCS,
  6. output reg [7:0] opcode, //contains the command which controls the FRAM
  7. output reg [23:0] addr, //contains current address that the memory is reading/writing
  8. reg [7:0] mem_data [1023:0], //contains the memory data
  9. reg [7:0] stat_reg, //stat_reg Bit 0 is 1 while waking up from Hibernate
  10. reg hibernate); //if true, memory is in hibernation
  11. reg [2:0] bitcnt_rcv; //counts the bits of the current byte when reading from SPI
  12. reg [2:0] bitcnt_snd; //counts sent bits for the current sent byte when writing to SPI
  13. reg [2:0] bitcnt_mem_write; //counts bits written to memory for the current received byte
  14. reg byte_received; //gets high when a full byte is received
  15. reg [7:0] byte_data_received; //contains the data of last received byte
  16. reg [3:0] byte_count; //counts the bytes of one message; is reset when a new message starts
  17. reg [7:0] byte_data_sent; //contains the sent byte after transmission
  18. reg send_data; //is set by opcode commands Read status register and Read memory when writing to SPI
  19. reg write_to_memory; ////is set by opcode WRITE, when high, incoming Bits from SI are written to the memory at a specific address.
  20. integer i; //countdown variable for status register read
  21. initial begin //values are set to startup values of FRAM
  22. opcode = 8'h00;
  23. stat_reg = 8'b00100000;
  24. addr = 24'h000000;
  25. byte_count = 4'b0000;
  26. byte_data_sent = 8'h00;
  27. bitcnt_rcv = 3'b000;
  28. bitcnt_snd = 3'b111;
  29. bitcnt_mem_write = 3'b111;
  30. byte_received = 1'b0;
  31. byte_data_received = 8'b00000000;
  32. send_data = 0;
  33. write_to_memory = 0;
  34. i = 8;
  35. hibernate = 0;
  36. $readmemh("memory.txt", mem_data); //initializes the memory with the contents of memory.txt
  37. end
  38. //receive incoming Bits and organize them bytewise
  39. always @(posedge SCK) begin
  40. if (bitcnt_rcv == 3'b111) begin
  41. byte_count <= byte_count + 4'b0001;
  42. end
  43. bitcnt_rcv <= bitcnt_rcv + 3'b001;
  44. byte_data_received <= {byte_data_received[6:0], SI};
  45. //when opcode WRÍTE is executed, the incoming bytes are written to memory
  46. if (write_to_memory == 1 && nCS == 0) begin
  47. mem_data[addr][bitcnt_mem_write+3'b001] = byte_data_received[0];
  48. if(bitcnt_mem_write == 3'b000) begin
  49. addr <= addr + 1;
  50. bitcnt_mem_write <= 3'b111;
  51. end
  52. bitcnt_mem_write <= bitcnt_mem_write - 1;
  53. end
  54. end
  55. always @(posedge SCK) byte_received <= (nCS == 0) && (bitcnt_rcv==3'b111);
  56. //TRANSMISSION
  57. //Read out memory and write to SPI, starts at addr
  58. always @(negedge SCK) begin
  59. if(send_data == 1 && nCS == 0)
  60. begin
  61. byte_data_sent <= {byte_data_sent[6:0], mem_data[addr][bitcnt_snd]};
  62. bitcnt_snd <= bitcnt_snd - 1;
  63. if (bitcnt_snd == 3'b000) begin
  64. addr <= addr + 1;
  65. bitcnt_snd <= 3'b111;
  66. end
  67. end
  68. //write status register to SO when opcode RDSR is sent
  69. else if (opcode == 8'h05 && nCS == 0 && i > 0) begin
  70. byte_data_sent <= {byte_data_sent[6:0], stat_reg[i-1]};
  71. i = i - 1;
  72. end
  73. end
  74. assign SO = byte_data_sent[0]; // MSB of the transmission is the lsb of byte_data_sent
  75. //the following block resets counters when a message has finished
  76. always @ (posedge nCS) begin
  77. if (opcode == 8'h06) begin //When WLEN opcode is executed, nCS needs to be reset.
  78. //Since the message is not finished, no counters should be reset when executing WLEN
  79. end
  80. else if (opcode == 8'hb9 && nCS == 1) hibernate = 1; //When hibernation opcode 8'hb9 is sent, the device goes into hibernation
  81. else begin
  82. byte_count = 8'h00;
  83. bitcnt_rcv = 3'b000;
  84. bitcnt_snd = 3'b111;
  85. bitcnt_mem_write = 3'b111;
  86. byte_data_received = 8'h00;
  87. end
  88. send_data = 0; //disables sending data
  89. write_to_memory = 0; // disables writing to memory
  90. stat_reg[1] = 0; //reset WEL when writing to memory has finished
  91. end
  92. //reset hibernate
  93. always @ (negedge nCS) hibernate = 0;
  94. //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.
  95. always @ (posedge byte_received) begin
  96. case (byte_count)
  97. //Byte 1 of message
  98. 4'h1: begin //counting starts at 1, not 0.
  99. case (byte_data_received)
  100. 8'h03: //READ Op-code
  101. opcode = 8'h03;
  102. 8'h06: begin //WREN Op-Code
  103. opcode = 8'h06;
  104. #25; //wait one clock for nCS to get low
  105. if (nCS == 1) stat_reg [1] = 1; //Set WEL Bit in Status Register after one clock cycle
  106. end
  107. //READ STATUS REGISTER Op-Code
  108. 8'h05: opcode = 8'h05;
  109. //HIBERNATE Op-Code
  110. 8'hb9: begin
  111. opcode = 8'hb9;
  112. end
  113. endcase
  114. end
  115. //Byte 2 of message
  116. 4'h2: begin
  117. case (byte_data_received)
  118. //WRITE
  119. 8'h02: //WRITE Op-code, only if WREN op-code was executed, WRITE Op-code is permitted.
  120. if (opcode == 8'h06) opcode = 8'h02;
  121. default:
  122. //READ - get highest address byte
  123. if (opcode == 8'h03) //upper four bits are not used and are always 0
  124. //the address is shifted in from right to left. Byte_data_received is the highest byte of the address
  125. addr <= {4'b0000, 12'h000, byte_data_received};
  126. endcase
  127. end
  128. //Byte 3 of message
  129. 4'h3: begin
  130. case (byte_data_received)
  131. default:
  132. //READ - get middle address byte
  133. if (opcode == 8'h03) //if opcode is read, the byte_data_received
  134. //is the next byte of the address, followed by 1 byte
  135. addr <= {4'b0000, 4'b0000, addr[7:0], byte_data_received};
  136. //WRITE - get highest address byte
  137. else if (opcode == 8'h02 && stat_reg[1] == 1'b1)
  138. addr <= {4'b0000, 12'h000, byte_data_received};
  139. endcase
  140. end
  141. //Byte 4 of message
  142. 4'h4: begin
  143. case (byte_data_received)
  144. default:
  145. //READ - get the lowest byte of the address
  146. if (opcode == 8'h03) begin
  147. addr <= {addr[15:0], byte_data_received};
  148. send_data = 1; //sets the flag which starts sending every bit out of SO at memory address "addr".
  149. end
  150. //WRITE - get middle address byte
  151. else if (opcode == 8'h02 && stat_reg[1] == 1'b1)
  152. addr <= {4'b000, 4'b0000, addr[7:0], byte_data_received};
  153. endcase
  154. end
  155. //Byte 5 of message
  156. 4'h5: begin
  157. case (byte_data_received)
  158. default:
  159. //WRITE - get lowest address byte and enable write_to_memory, the following bytes are data.
  160. if (opcode == 8'h02 && stat_reg[1] == 1'b1) begin
  161. addr <= {addr[15:0], byte_data_received};
  162. write_to_memory = 1; //set write to memory and wait one clock
  163. end
  164. endcase
  165. end
  166. endcase
  167. end
  168. endmodule