URL
https://opencores.org/ocsvn/yifive/yifive/trunk
Subversion Repositories yifive
[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [spi_master/] [src/] [spim_regs.sv] - Rev 21
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////////// //////// SPI WishBone Register I/F Module //////// //////// This file is part of the YIFive cores project //////// http://www.opencores.org/cores/yifive/ //////// //////// Description //////// SPI WishBone I/F module //////// This block support following functionality //////// 1. Direct SPI Read memory support for address rang //////// 0x0000 to 0x0FFF_FFFF - Use full for Instruction //////// Data Memory fetch //////// 2. SPI Local Register Access //////// 3. Indirect register way to access SPI Memory //////// //////// To Do: //////// nothing //////// //////// Author(s): //////// - Dinesh Annayya, dinesha@opencores.org //////// //////// Revision : //////// V.0 - June 8, 2021 //////// ////////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2000 Authors and OPENCORES.ORG //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer. //////// //////// This source file is free software; you can redistribute it //////// and/or modify it under the terms of the GNU Lesser General //////// Public License as published by the Free Software Foundation; //////// either version 2.1 of the License, or (at your option) any //////// later version. //////// //////// This source is distributed in the hope that it will be //////// useful, but WITHOUT ANY WARRANTY; without even the implied //////// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //////// PURPOSE. See the GNU Lesser General Public License for more //////// details. //////// //////// You should have received a copy of the GNU Lesser General //////// Public License along with this source; if not, download it //////// from http://www.opencores.org/lgpl.shtml //////// //////////////////////////////////////////////////////////////////////////module spim_regs #( parameter WB_WIDTH = 32) (input logic mclk,input logic rst_n,input logic wbd_stb_i, // strobe/requestinput logic [WB_WIDTH-1:0] wbd_adr_i, // addressinput logic wbd_we_i, // writeinput logic [WB_WIDTH-1:0] wbd_dat_i, // data outputinput logic [3:0] wbd_sel_i, // byte enableoutput logic [WB_WIDTH-1:0] wbd_dat_o, // data inputoutput logic wbd_ack_o, // acknowlegementoutput logic wbd_err_o, // erroroutput logic [7:0] spi_clk_div,output logic spi_clk_div_valid,input logic [8:0] spi_status,// Towards SPI TX/RX FSMoutput logic spi_req,output logic [31:0] spi_addr,output logic [5:0] spi_addr_len,output logic [7:0] spi_cmd,output logic [5:0] spi_cmd_len,output logic [7:0] spi_mode_cmd,output logic spi_mode_cmd_enb,output logic [3:0] spi_csreg,output logic [15:0] spi_data_len,output logic [15:0] spi_dummy_rd_len,output logic [15:0] spi_dummy_wr_len,output logic spi_swrst,output logic spi_rd,output logic spi_wr,output logic spi_qrd,output logic spi_qwr,output logic [31:0] spi_wdata,input logic [31:0] spi_rdata,input logic spi_ack);//----------------------------// Register Decoding// ---------------------------parameter REG_CTRL = 4'b0000;parameter REG_CLKDIV = 4'b0001;parameter REG_SPICMD = 4'b0010;parameter REG_SPIADR = 4'b0011;parameter REG_SPILEN = 4'b0100;parameter REG_SPIDUM = 4'b0101;parameter REG_SPIWDATA = 4'b0110;parameter REG_SPIRDATA = 4'b0111;parameter REG_STATUS = 4'b1000;// Init FSMparameter SPI_INIT_IDLE = 3'b000;parameter SPI_INIT_CMD_WAIT = 3'b001;parameter SPI_INIT_WREN_CMD = 3'b010;parameter SPI_INIT_WREN_WAIT = 3'b011;parameter SPI_INIT_WRR_CMD = 3'b100;parameter SPI_INIT_WRR_WAIT = 3'b101;//---------------------------------------------------------// Variable declartion// -------------------------------------------------------logic spi_init_done ;logic [2:0] spi_init_state ;logic spim_mem_req ;logic spim_reg_req ;logic spim_wb_req ;logic spim_wb_req_l ;logic [WB_WIDTH-1:0] spim_wb_wdata ;logic [WB_WIDTH-1:0] spim_wb_addr ;logic spim_wb_ack ;logic spim_wb_we ;logic [3:0] spim_wb_be ;logic [WB_WIDTH-1:0] spim_reg_rdata ;logic [WB_WIDTH-1:0] spim_wb_rdata ;logic [WB_WIDTH-1:0] reg_rdata ;// Control Signal Generated from Reg to SPI Accesslogic reg2spi_req;logic [31:0] reg2spi_addr;logic [5:0] reg2spi_addr_len;logic [31:0] reg2spi_cmd;logic [5:0] reg2spi_cmd_len;logic [3:0] reg2spi_csreg;logic [15:0] reg2spi_data_len;logic reg2spi_mode_enb; // mode enablelogic [7:0] reg2spi_mode; // modelogic [15:0] reg2spi_dummy_rd_len;logic [15:0] reg2spi_dummy_wr_len;logic reg2spi_swrst;logic reg2spi_rd;logic reg2spi_wr;logic reg2spi_qrd;logic reg2spi_qwr;logic [31:0] reg2spi_wdata;//------------------------------------------------------------------// Priority given to mem2spi request over Reg2Spiassign spi_req = (spim_mem_req && !spim_wb_we) ? 1'b1 : reg2spi_req;assign spi_addr = (spim_mem_req && !spim_wb_we) ? {spim_wb_addr[23:0],8'h0} : reg2spi_addr;assign spi_addr_len = (spim_mem_req && !spim_wb_we) ? 24 : reg2spi_addr_len;assign spi_cmd = (spim_mem_req && !spim_wb_we) ? 8'hEB : reg2spi_cmd;assign spi_cmd_len = (spim_mem_req && !spim_wb_we) ? 8 : reg2spi_cmd_len;assign spi_mode_cmd = (spim_mem_req && !spim_wb_we) ? 8'h00 : reg2spi_mode;assign spi_mode_cmd_enb = (spim_mem_req && !spim_wb_we) ? 1 : reg2spi_mode_enb;assign spi_csreg = (spim_mem_req && !spim_wb_we) ? '1 : reg2spi_csreg;assign spi_data_len = (spim_mem_req && !spim_wb_we) ? 'h20 : reg2spi_data_len;assign spi_dummy_rd_len = (spim_mem_req && !spim_wb_we) ? 'h20 : reg2spi_dummy_rd_len;assign spi_dummy_wr_len = (spim_mem_req && !spim_wb_we) ? 0 : reg2spi_dummy_wr_len;assign spi_swrst = (spim_mem_req && !spim_wb_we) ? 0 : reg2spi_swrst;assign spi_rd = (spim_mem_req && !spim_wb_we) ? 0 : reg2spi_rd;assign spi_wr = (spim_mem_req && !spim_wb_we) ? 0 : reg2spi_wr;assign spi_qrd = (spim_mem_req && !spim_wb_we) ? 1 : reg2spi_qrd;assign spi_qwr = (spim_mem_req && !spim_wb_we) ? 0 : reg2spi_qwr;assign spi_wdata = (spim_mem_req && !spim_wb_we) ? 0 : reg2spi_wdata;//---------------------------------------------------------------// Address Decoding// 0x0000_0000 - 0x0FFF_FFFF - SPI FLASH MEMORY ACCESS - 256MB// 0x1000_0000 - - SPI Register Access// --------------------------------------------------------------assign spim_mem_req = ((spim_wb_req) && spim_wb_addr[31:28] == 4'b0000);assign spim_reg_req = ((spim_wb_req) && spim_wb_addr[31:28] == 4'b0001);assign wbd_dat_o = spim_wb_rdata;assign wbd_ack_o = spim_wb_ack;assign wbd_err_o = 1'b0;// To reduce the load/Timing Wishbone I/F, all the variable are registeredalways_ff @(negedge rst_n or posedge mclk) beginif ( rst_n == 1'b0 ) beginspim_wb_req <= '0;spim_wb_req_l <= '0;spim_wb_wdata <= '0;spim_wb_rdata <= '0;spim_wb_addr <= '0;spim_wb_be <= '0;spim_wb_we <= '0;spim_wb_ack <= '0;end else beginif(spi_init_done) begin // Wait for internal SPI Init Donespim_wb_req <= wbd_stb_i && (spi_ack == 0) && (spim_wb_ack==0);spim_wb_req_l <= spim_wb_req;spim_wb_wdata <= wbd_dat_i;spim_wb_addr <= wbd_adr_i;spim_wb_be <= wbd_sel_i;spim_wb_we <= wbd_we_i;// If there is Reg2Spi read Access, Register the Read Dataif(reg2spi_req && (reg2spi_rd || reg2spi_qrd ) && spi_ack)spim_reg_rdata <= spi_rdata;if(!spim_wb_we && spim_wb_req && spi_ack)spim_wb_rdata <= spi_rdata;else if (spim_reg_req)spim_wb_rdata <= reg_rdata;// For safer design, we have generated ack after 2 cycle latter to// cross-check current request is towards SPI or notspim_wb_ack <= (spi_req && spim_wb_req) ? spi_ack :((spim_wb_ack==0) && spim_wb_req && spim_wb_req_l) ;endendendinteger byte_index;always_ff @(negedge rst_n or posedge mclk) beginif ( rst_n == 1'b0 ) beginreg2spi_swrst <= 1'b0;reg2spi_rd <= 1'b0;reg2spi_wr <= 1'b0;reg2spi_qrd <= 1'b0;reg2spi_qwr <= 1'b0;reg2spi_cmd <= 'h0;reg2spi_addr <= 'h0;reg2spi_cmd_len <= 'h0;reg2spi_addr_len <= 'h0;reg2spi_data_len <= 'h0;reg2spi_wdata <= 'h0;reg2spi_mode_enb <= 'h0;reg2spi_mode <= 'h0;reg2spi_dummy_rd_len <= 'h0;reg2spi_dummy_wr_len <= 'h0;reg2spi_csreg <= 'h0;reg2spi_req <= 'h0;spi_clk_div_valid <= 1'b0;spi_clk_div <= 'h2;spi_init_done <= 'h0;spi_init_state <= SPI_INIT_IDLE;endelse if (spi_init_done == 0) begincase(spi_init_state)SPI_INIT_IDLE:beginreg2spi_rd <= 'h0;reg2spi_wr <= 'h1; // SPI Write Reqreg2spi_qrd <= 'h0;reg2spi_qwr <= 'h0;reg2spi_swrst <= 'h0;reg2spi_csreg <= 'h1;reg2spi_cmd[7:0] <= 'hAB; // POWER UP commandreg2spi_mode[7:0] <= 'h0;reg2spi_cmd_len <= 'h8;reg2spi_addr_len <= 'h0;reg2spi_data_len <= 'h0;reg2spi_wdata <= 'h0;reg2spi_req <= 'h1;spi_init_state <= SPI_INIT_CMD_WAIT;endSPI_INIT_CMD_WAIT:beginif(spi_ack) beginreg2spi_req <= 1'b0;spi_init_state <= SPI_INIT_WREN_CMD;endendSPI_INIT_WREN_CMD:beginreg2spi_rd <= 'h0;reg2spi_wr <= 'h1; // SPI Write Reqreg2spi_qrd <= 'h0;reg2spi_qwr <= 'h0;reg2spi_swrst <= 'h0;reg2spi_csreg <= 'h1;reg2spi_cmd[7:0] <= 'h6; // WREN commandreg2spi_mode[7:0] <= 'h0;reg2spi_cmd_len <= 'h8;reg2spi_addr_len <= 'h0;reg2spi_data_len <= 'h0;reg2spi_wdata <= 'h0;reg2spi_req <= 'h1;spi_init_state <= SPI_INIT_WREN_WAIT;endSPI_INIT_WREN_WAIT:beginif(spi_ack) beginreg2spi_req <= 1'b0;spi_init_state <= SPI_INIT_WRR_CMD;endendSPI_INIT_WRR_CMD:beginreg2spi_rd <= 'h0;reg2spi_wr <= 'h1; // SPI Write Reqreg2spi_qrd <= 'h0;reg2spi_qwr <= 'h0;reg2spi_swrst <= 'h0;reg2spi_csreg <= 'h1;reg2spi_cmd[7:0] <= 'h1; // WRR commandreg2spi_mode[7:0] <= 'h0;reg2spi_cmd_len <= 'h8;reg2spi_addr_len <= 'h0;reg2spi_data_len <= 'h10;reg2spi_wdata <= {8'h0,8'h2,16'h0}; // <sr1[7:0]><<cr1[7:0]><16'h0> cr1[1] = 1 indicate quad modereg2spi_req <= 'h1;spi_init_state <= SPI_INIT_WRR_WAIT;endSPI_INIT_WRR_WAIT:beginif(spi_ack) beginreg2spi_req <= 1'b0;spi_init_done <= 'h1;endendendcaseend else if (spim_reg_req & spim_wb_we )begincase(spim_wb_addr[7:4])REG_CTRL:beginif ( spim_wb_be[0] == 1 )beginreg2spi_rd <= spim_wb_wdata[0];reg2spi_wr <= spim_wb_wdata[1];reg2spi_qrd <= spim_wb_wdata[2];reg2spi_qwr <= spim_wb_wdata[3];reg2spi_swrst <= spim_wb_wdata[4];reg2spi_req <= 1'b1;endif ( spim_wb_be[1] == 1 )beginreg2spi_csreg <= spim_wb_wdata[11:8];endendREG_CLKDIV:if ( spim_wb_be[0] == 1 )beginspi_clk_div <= spim_wb_wdata[7:0];spi_clk_div_valid <= 1'b1;endREG_SPICMD: beginif ( spim_wb_be[0] == 1 )reg2spi_cmd[7:0] <= spim_wb_wdata[7:0];if ( spim_wb_be[1] == 1 )reg2spi_mode[7:0] <= spim_wb_wdata[15:8];endREG_SPIADR:for (byte_index = 0; byte_index < 4; byte_index = byte_index+1 )if ( spim_wb_be[byte_index] == 1 )reg2spi_addr[byte_index*8 +: 8] <= spim_wb_wdata[(byte_index*8) +: 8];REG_SPILEN:beginif ( spim_wb_be[0] == 1 ) beginreg2spi_mode_enb <= spim_wb_wdata[6];reg2spi_cmd_len <= spim_wb_wdata[5:0];endif ( spim_wb_be[1] == 1 )reg2spi_addr_len <= spim_wb_wdata[13:8];if ( spim_wb_be[2] == 1 )reg2spi_data_len[7:0] <= spim_wb_wdata[23:16];if ( spim_wb_be[3] == 1 )reg2spi_data_len[15:8] <= spim_wb_wdata[31:24];endREG_SPIDUM:beginif ( spim_wb_be[0] == 1 )reg2spi_dummy_rd_len[7:0] <= spim_wb_wdata[7:0];if ( spim_wb_be[1] == 1 )reg2spi_dummy_rd_len[15:8] <= spim_wb_wdata[15:8];if ( spim_wb_be[2] == 1 )reg2spi_dummy_wr_len[7:0] <= spim_wb_wdata[23:16];if ( spim_wb_be[3] == 1 )reg2spi_dummy_wr_len[15:8] <= spim_wb_wdata[31:24];endREG_SPIWDATA: beginreg2spi_wdata <= spim_wb_wdata;endendcaseendelsebeginif(spi_ack && spim_reg_req)reg2spi_req <= 1'b0;endendwire [3:0] reg_addr = spim_wb_addr[7:4];// implement slave model register read muxalways_combbeginreg_rdata = '0;if(spim_reg_req) begincase(reg_addr)REG_CTRL:reg_rdata[31:0] = { 20'h0,reg2spi_csreg,3'b0,reg2spi_swrst,reg2spi_qwr,reg2spi_qrd,reg2spi_wr,reg2spi_rd};REG_CLKDIV:reg_rdata[31:0] = {24'h0,spi_clk_div};REG_SPICMD:reg_rdata[31:0] = {16'h0,reg2spi_mode,reg2spi_cmd};REG_SPIADR:reg_rdata[31:0] = reg2spi_addr;REG_SPILEN:reg_rdata[31:0] = {reg2spi_data_len,2'b00,reg2spi_addr_len,1'b0,reg2spi_mode_enb,reg2spi_cmd_len};REG_SPIDUM:reg_rdata[31:0] = {reg2spi_dummy_wr_len,reg2spi_dummy_rd_len};REG_SPIWDATA:reg_rdata[31:0] = reg2spi_wdata;REG_SPIRDATA:reg_rdata[31:0] = spim_reg_rdata;REG_STATUS:reg_rdata[31:0] = {23'h0,spi_status};endcaseendendendmodule
