`timescale 1ns / 1ps module m25p16_spi_core( input clk_i, input rst_i, input [4:0] opcode_i, input [31:0] info_i, input [31:0] dat_i, output [31:0] dat_o, output dat_o_read, output dat_o_valid, input [31:0] adr_i, output finish_o ); wire spi_finish; reg [31:0] data; reg [31:0] info; reg [7:0] cnt; //*********************************** // SPI M25P16 Core state //*********************************** // Memory for storing state reg[7:0] state = IDLE_S; reg[7:0] next_state; localparam OPCODE_READING_DATA = 1, OPCODE_WRITING_DATA = 2, OPCODE_ERASING_SECTOR = 3, OPCODE_BULK_ERASING = 4, OPCODE_READING_STATUS = 5, OPCODE_WRITING_STATUS = 6; localparam IDLE_S = 0, WRITING_DATA_WRITE_ENABLE_S = 1, WRITING_DATA_WRITE_INSTR_S = 2, WRITING_DATA_WRITE_DATA_S = 3, WRITING_DATA_WRITE_DISABLE_S = 4, FINISH_S = 64; always @* case( state ) IDLE_S: info = info_i; endcase always @( posedge clk_i, posedge rst_i ) if( rst_i ) state <= IDLE_S; else state <= next_state; always @* begin next_state = state; case( state ) IDLE_S: if( opcode_i == OPCODE_WRITING_DATA ) next_state = WRITING_DATA_WRITE_ENABLE_S; WRITING_DATA_WRITE_ENABLE_S: if( spi_finish ) next_state = WRITING_DATA_WRITE_INSTR_S; WRITING_DATA_WRITE_INSTR_S: if( next_w ) next_state = WRITING_DATA_WRITE_DATA_S; WRITING_DATA_WRITE_DATA_S: if( spi_finish ) next_state = WRITING_DATA_WRITE_DISABLE_S; WRITING_DATA_WRITE_DISABLE_S: if( spi_finish ) next_state = FINISH_S; FINISH_S: next_state = IDLE_S; endcase end always @* case( next_state ) WRITING_DATA_WRITE_INSTR_S: cnt = 4; WRITING_DATA_WRITE_ENABLE_S, WRITING_DATA_WRITE_DISABLE_S: cnt = 1; WRITING_DATA_WRITE_DATA_S: cnt = info[7:0] << 2; endcase always @* case( state ) WRITING_DATA_WRITE_DATA_S: data = dat_i; endcase always @* case( next_state ) WRITING_DATA_WRITE_ENABLE_S: data = 32'hAA; WRITING_DATA_WRITE_INSTR_S: data = 32'hFF000000 | adr_i[23:0]; WRITING_DATA_WRITE_DATA_S: data = dat_i; WRITING_DATA_WRITE_DISABLE_S: data = 32'hDD; endcase //*********************************** // SPI Routine //*********************************** wire spi_miso_i, spi_sclk_o, spi_mosi_o, spi_ss_i; assign spi_rd_i = 1'b0; // TODO: unused assign spi_wr_i = (WRITING_DATA_WRITE_ENABLE_S || WRITING_DATA_WRITE_INSTR_S || WRITING_DATA_WRITE_DATA_S || WRITING_DATA_WRITE_DISABLE_S); assign spi_sclk_i = clk_i; wire [31:0] rx_o; // TODO: unused wire next_o; wire next_w; assign next_o = ( state == WRITING_DATA_WRITE_DATA_S ? dat_o_read : next_w ); spi_routine spi_routine( .clk_i(clk_i), .rst_i(1'b0), .sclk_o(spi_sclk_o), .ss_i(spi_ss_i), .mosi_o(spi_mosi_o), .miso_i(spi_miso_i), .rx_o(rx_o), .tx_i(data), .wr_i(spi_wr_i), .rd_i(spi_rd_i), .cnt_i(cnt), .next_o(next_o), .finish_o(spi_finish) ); assign finish_o = ( state == FINISH_S ? 1 : 0 ); endmodule