////////////////////////////////////////////////////////////////////////////////// // Company : NPK TAIR // Engineer : Yuri Donskoy // // Create Date (dd/mm/yyyy) : 16.05.2019 // Design Name : // Module Name : // Project Name : // Target Devices : // Tool versions : // Description : // // Dependencies : // // Revision : 0.01 - File Created // Additional Comments : // ////////////////////////////////////////////////////////////////////////////////// module PeriphSpiInit ( clk_i, rst_i, enable_i, mosi_o, sck_o, ss_o, done_o ); //================================================================================ // // FUNCTIONS // //================================================================================ function integer bit_num; input integer value; begin bit_num = 0; while (value > 0) begin value = value >> 1; bit_num = bit_num + 1; end end endfunction //================================================================================ // // PARAMETER/LOCALPARAM // //================================================================================ parameter DATA_WIDTH = 24; parameter DATA_NUM = 26; parameter ROM_INIT_FILE = "./initFiles/AdcInitData.txt"; parameter FILE_DATA_BASE = "HEX"; parameter SPI_CLK_DIVISOR_POWER = 4; parameter SPI_CPOL = 0; parameter SPI_CPHA = 0; parameter SPI_DATA_DIRECTION = "MSB"; // MSB or LSB parameter SPI_EN_START_DELAY = "NO"; // YES or NO localparam ROM_ADDR_WIDTH = bit_num(DATA_NUM); //================================================================================ // // STATE MACHINE STATES // //================================================================================ localparam [7:0] SM_RST_S = 8'd0; localparam [7:0] SM_SEND_DATA_S = 8'd2; localparam [7:0] SM_READ_DATA_S = 8'd3; localparam [7:0] SM_WAIT_SPI_S = 8'd4; localparam [7:0] SM_DONE_S = 8'd5; //================================================================================ // // PORTS // //================================================================================ input clk_i; input rst_i; input enable_i; output mosi_o; output sck_o; output ss_o; output done_o; //================================================================================ // // REG/WIRE // //================================================================================ reg [ROM_ADDR_WIDTH-1:0] rom_addr; reg rom_valid; wire [DATA_WIDTH-1:0] rom_data; reg [ROM_ADDR_WIDTH-1:0] rom_addr_next; wire spi_ready; reg [7:0] sm_curr_state; reg [7:0] sm_next_state; wire data_end_flag; //================================================================================ // // INTEGER/GENVAR // //================================================================================ //================================================================================ // // ASSIGN // //================================================================================ assign data_end_flag = (rom_addr == DATA_NUM); assign done_o = sm_curr_state == SM_DONE_S; //================================================================================ // // CODING // //================================================================================ SpiMaster #( .CLK_DIVISOR_POWER (SPI_CLK_DIVISOR_POWER), .DATA_WIDTH (DATA_WIDTH), .CPOL (SPI_CPOL), .CPHA (SPI_CPHA), .DATA_DIRECTION (SPI_DATA_DIRECTION), .EN_START_DELAY (SPI_EN_START_DELAY) ) SpiMaster ( .clk_i (clk_i), .rst_i (rst_i), .data_i (rom_data), .valid_i (rom_valid), .ready_o (spi_ready), .mosi_o (mosi_o), .sck_o (sck_o), .ss_o (ss_o) ); SinglePortRom #( .DATA_WIDTH (DATA_WIDTH), .ADDR_WIDTH (ROM_ADDR_WIDTH), .INIT_FILE_NAME (ROM_INIT_FILE), .DATA_BASE (FILE_DATA_BASE) ) Rom ( .clk_i (clk_i), .addr_i (rom_addr), .q_o (rom_data) ); always @(posedge clk_i or posedge rst_i) begin if (rst_i) begin sm_curr_state <= 0; rom_addr <= SM_RST_S; end else begin sm_curr_state <= sm_next_state; rom_addr <= rom_addr_next; end end always @(*) begin sm_next_state = 0; rom_addr_next = rom_addr; rom_valid = 1'b0; case(sm_curr_state) SM_RST_S : begin if (enable_i) begin sm_next_state = SM_SEND_DATA_S; end else begin sm_next_state = SM_RST_S; end end SM_SEND_DATA_S : begin rom_valid = 1'b1; sm_next_state = SM_SEND_DATA_S; if (spi_ready) begin rom_addr_next = rom_addr + {{(ROM_ADDR_WIDTH-1){1'b0}}, 1'b1}; sm_next_state = SM_READ_DATA_S; end end SM_READ_DATA_S : begin if (data_end_flag) begin sm_next_state = SM_WAIT_SPI_S; end else begin sm_next_state = SM_SEND_DATA_S; end end SM_WAIT_SPI_S : begin if (spi_ready) begin sm_next_state = SM_DONE_S; end else begin sm_next_state = SM_WAIT_SPI_S; end end SM_DONE_S : begin sm_next_state = SM_DONE_S; end endcase end endmodule