⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi_burst.v

📁 Verilog block SPI for Burst R/W Operation
💻 V
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//                         FileName: "spi_burst.v"                           //
//                                                                           //
//  Description: This is SPI control logic. One/Two Byte Data is transmitted //
// and one byte data is received by 8051 from SPI. Burst data is transmitted //
//               and received from/to buffer by hardware.                    //
//                The main function are:                                     //
//                 a. one/burst Read                                         //
//                 b. one/burst Write                                        //
//                 c. Two bytes Write                                        //
//                                                                           //
//   Author       : Well.yu                                                  //
//                                                                           //
//                                                                           //
//   Revision History                                                        //
//                                                                           //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

//CTRL Configure
//1.CLOCK:                          ctrl[7]
//      a. mck==mcu_clk           : XBYTE[0x03f1] |= 0x80 ;
//      b. mck==1/2*(N+1)*mcu_clk : XBYTE[0x03f1] &= 0x7f ; 
//2.Sample edge selection:          ctrl[6]
//      a. Sample Data from mdi at mck rising  edge : XBYTE[0x03f1] &= 0xbf ;
//      b. Sample Data from mdi at mck falling edge : XBYTE[0x03f1] |= 0x40 ;
//3.Clock divide Frequency Counter: ctrl[5:0]
//      mck==1/2*(N+1)*mcu_clk    : XBYTE[0x03f1]  = data ;(data<64,data==N)



//Five Types Operation
//1:One byte Write  ->   XBYTE[0x03fb]  = data ;
//2:Burst Write     ->   XBYTE[0x03fe]  = 0x01 ; 
//3:One byte Read   ->   XBYTE[0x03fe]  = 0x0E ;
//4:Burst Read      ->   XBYTE[0x03fe]  = 0x0A ;
//5:Two bytes Wriet -> 1.XBYTE[0x03fd]  = 0x0F ;
//                     2.XBYTE[0x03fc]  = data2; 
//                     3.XBYTE[0x03fb]  = data1;

//Reg Map :  0x03f0~0x03ff
`define      SPI_TEST_SEL      8'h60          
`define      SPI_CTL           8'h61 
`define      XMIT_LEN_L        8'h62 
`define      XMIT_LEN_H        8'h63 
`define      RECV_LEN_L        8'h64 
`define      RECV_LEN_H        8'h65
`define      SPI_S_RST         8'h69
`define      SPI_STAT_M        8'h6a
`define      XMIT_ONE_D        8'h6b
`define      XMIT_TWO_D        8'h6c 
`define      XMIT_BIT_L        8'h6d 
`define      SPI_CMD_WR        8'h6e
`define      SPI_STATUS        8'h6f 

`timescale 1ns/10ps
module spi(
///////spi bus//////////
       mdi,
       mdo,
       mck,
///////ctrl block//////
       mcu_clk,
       reset_n,
       //reset_s,
       spi_en,
//////burst read ctrl///
       spidat,
       spidat_vld,
//////mcu interface//////       
       wr_8051,
       rd_8051,
       addr,
       data_in,
       data_out,
//////burst write ctrl///
       buf_rd_mcu,
       buf_dat,
//////test bus//////////
       spi_test_bus
       );
////////////////////////        Ports         ///////////////////////////////////////////////////
input         mdi;              // master data in, connect to flash pin 'sdo'
output        mdo;              // master data out, connect to flash pin 'sdi'
output        mck;              // master clock, connect to flash pin 'clk'
input         mcu_clk;          // system clock, 30Mhz
input         reset_n;          // system reset:'0'
//input         reset_s;          // soft reset  :'0'
input         spi_en;           // enable SPI block : '1'-enable;'0'-disable

output [7:0]  spidat;           // 8051 control transfer data, e.x, spi command is transfered
                                // by this regsiter. The second function is receiving data
                                // serially from SPI flash
output        spidat_vld;       // valid signal for spidat when transfer data from SPI to buf

input  [7:0]  addr;             // 8051 write/read address
input  [7:0]  data_in;          // from 8051 data
output [7:0]  data_out;         // to   8051 data
input         wr_8051;          // 8051 write enable
input         rd_8051;          // 8051 read  enable

output        buf_rd_mcu;       // read enable to read data from buf1 or buf2
input  [7:0]  buf_dat;          // data which will be xmitted from buffer to SPI

//output [7:0]  spictrl ;         // SPI Ctrl Register : default 8'h84 -> 1000,0100
//output [7:0]  bufwl ;           // from Buffer Write data  Length Low  :default 8'hff - 256Bytes
//output [7:0]  bufwh ;           // from Buffer Write data  Length High :default 8'h00
//output [7:0]  bufrl ;           // to   Buffer Read  data  Length Low  :default 8'hff - 256Bytes
//output [7:0]  bufrh ;           // to   Buffer Read  data  Length High :default 8'h00
output [15:0] spi_test_bus ;


//////////////////////         Signals        //////////////////////////////////////////////////////

wire          mcu_clk_sel;      // '1' selects MCU CLK for SPI  :30MHz
//wire          mcu_clk_h_sel;    // '1' selects Half of MCU CLK for SPI :15MHz
                                // {mcu_clk_sel,mcu_clk_h_sel}== 2'b00, then select 7.5Mhz
wire          rd_one_byte ;
wire          rcv_edge_sel;
wire          spi_dir ;
//wire   [7:0]  spictrl ;
//wire   [7:0]  bufwl ;
//wire   [7:0]  bufwh ;
//wire   [7:0]  bufrl ;
//wire   [7:0]  bufrh ;

wire   [7:0]  addr  ;
wire   [7:0]  data_in  ;
reg    [7:0]  data_out;

reg    [3:0]  state, state_nxt;
wire          cmd_lat;
reg           cmd_lat_d1;
wire          xmit_done;
reg    [7:0]  xmit_cnt;
reg    [7:0]  dat_out,dat_out2;
reg    [7:0]  buf_dat_lch;
reg           mck_en;
wire          mck;
reg           mdo;
wire          xmit_nxt;

wire          spi_cmd_sent;
reg    [15:0] buf_rd_cnt;
reg    [3:0]  sta_d, sta_d_nxt;
reg    [2:0]  cnt7;
reg           buf_rd /* synthesis syn_keep = 1 */;
reg           buf_rd_d1;
wire          buf_rd_mcu;
reg           xmit_nxt_dat;
reg    [7:0]  spidat;
reg           rd_en;
reg           xmit_nxt_dat_d1;
reg           xmit_done_d1;
reg           spidat_vld_reg, spidat_vld_pre_d1;
wire          spidat_vld_pre;
wire		      spidat_vld;
reg    [12:0] cnt7_for_rd;

reg           spi_work;         // '1':mck is working  '0': mck is idle
wire          spi_busy;         // Burst write Busy ->'1':Idle->'0'
wire					mck_jump;

reg           cmd_lat_24, ctrl_3_24m;


reg    [1:0]  bus_sel;  
reg    [7:0]  ctrl ; // SPI control register:
                     // ctrl[7]   -> mcu_clk_sel                             R/W
                     // ctrl[6]   -> Sample received data clock edge select  R/W
                     // ctrl[5:0] -> Divide Frequency Coefficient            R/W
reg    [7:0]  bwdl ; // Burst Write Data Length Low , default 8'hff - 256Bytes
reg    [7:0]  bwdh ; // Burst Write Data Length High, default 8'h00
reg    [7:0]  brdl ; // Burst Read  Data Length Low , default 8'hff - 256Bytes
reg    [7:0]  brdh ; // Burst Read  Data Length High, default 8'h00
reg    [7:0]  bitl ; // Bit   Write Data Length Low , default 8'h07 - 8Bits
reg    [7:0]  cmd  ; // cmd[3]  -> SPI direction :'1'->Read '0'->Write       R/W
                     // cmd[2]  -> Read One Byte Data                        R/W
                     // cmd[1]  -> Start SPI Read operation '1'              W
                     // cmd[0]  -> Start SPI Burst Write operation           W
reg    [7:0]  sbdw ; // the Second Byte in Double Bytes Write
reg           soft_rst;//soft reset  :'0' active
reg    [15:0] spi_test_bus ;// Inside SPI Signal Bus for Test                

wire          reset_s;
wire          clk ;  // spi clk : 30MHz,15MHz,7.5MHz
//reg    [1:0]  spi_divcnt ;
reg    [6:0]  spi_clk_cnt;
reg           clk_conv_zero;
reg           clk_conv_one ;
wire   [5:0]  clkdiv;
wire   [6:0]  clk_divx2;
wire   [6:0]  clkdiv_add1;
wire          spi_clk_trig;
reg           spi_div_clk;
reg           spi_divclk_ok;//SPI Clock is OK : '1' -> OK ; '0' -> NOT

parameter   IDLE  = 4'h0,  // idle state, this machine controls command sending
            START = 4'h1,  // start to xmit command
            XMIT  = 4'h2;  // xmitting command

parameter   IDLE_D  = 4'h0, // idle state, this machinen controls data sending
            BEGIN   = 4'h1, // begin to xmit data
            BUF_RD = 4'h2,  // reading data from buf1
            wait   = 4'h3,  // waiting next buffer, if there are more data




wire [15:0] bwdt     = {1'b0,bwdh[6:0],bwdl}+1'b1;

assign      reset_s  = soft_rst && spi_en ;
assign			spi_busy = (sta_d == BUF1_RD) ? 1'b1 : 1'b0;



assign      mcu_clk_sel   = ctrl[7] ;
assign      rcv_edge_sel  = ctrl[6] ;



assign      spi_dir       = cmd[3] ;
assign      rd_one_byte   = cmd[2] ;
assign      spi_cmd_sent  = cmd[0] ;




/////////////////////////////////////     CLK GEN     ///////////////////////////////////

assign clk = mcu_clk_sel   ? mcu_clk : spi_div_clk ;


assign clkdiv      = ctrl[5:0]     ;
assign clk_divx2   = {clkdiv,1'b1} ;
assign clkdiv_add1 = clkdiv + 1'b1 ;

always @(posedge mcu_clk or negedge reset_n)
begin
	if(!reset_n)
	  spi_clk_cnt <= #1 7'h00 ;
	else if(!reset_s)
	  spi_clk_cnt <= #1 7'h00 ;
	else if(spi_clk_cnt == clk_divx2)
	  spi_clk_cnt <= #1 7'h00 ;
	else
	  spi_clk_cnt <= #1 spi_clk_cnt + 1'b1 ;
end 

always @(posedge mcu_clk or negedge reset_n)
begin
	if(!reset_n)
	  clk_conv_one <= #1 1'b0 ;
	else if(!reset_s)
    clk_conv_one <= #1 1'b0 ;
  else if(spi_clk_cnt == clkdiv_add1)
    clk_conv_one <= #1 1'b1 ;
  else
    clk_conv_one <= #1 1'b0 ;
end

always @(posedge mcu_clk or negedge reset_n)
begin
	if(!reset_n)
	  clk_conv_zero <= #1 1'b0 ;
	else if(!reset_s)
    clk_conv_zero <= #1 1'b0 ;
  else if(spi_clk_cnt == 7'h00)
    clk_conv_zero <= #1 1'b1 ;
  else
    clk_conv_zero <= #1 1'b0 ;
end

always @(posedge mcu_clk or negedge reset_n)
begin
	if(!reset_n)
	  spi_div_clk <= #1 1'b0 ;
	else if(!reset_s)
    spi_div_clk <= #1 1'b0 ;
  else if(clk_conv_one)
    spi_div_clk <= #1 1'b1 ;
  else if(clk_conv_zero)
    spi_div_clk <= #1 1'b0 ;
end

assign spi_clk_trig = mcu_clk_sel ? 1'b1 : clk_conv_one ;







/////////////////////////////////////////        state machine for byte data sending      //////////////////////////////
always @(posedge mcu_clk or negedge reset_n)
begin
  if (!reset_n)
    state <= #1 4'h0;
  else if (!reset_s)
    state <= #1 4'h0;
  else if (spi_clk_trig)
    state <= #1 state_nxt;
end

always @(state or cmd_lat_24 or xmit_done)
begin
  case (state)
  IDLE :
        if (cmd_lat_24)
          state_nxt = START;
        else
          state_nxt = IDLE;
  START:
          state_nxt = XMIT;
  XMIT :
        if (xmit_done)
          state_nxt = IDLE;
        else
          state_nxt = XMIT;
  default:
          state_nxt = IDLE;
  endcase
end

// state machine for data burst sending
always @(posedge mcu_clk or negedge reset_n)
begin
  if (!reset_n)
    sta_d <= #1 4'h0;
  else if (!reset_s)
    sta_d <= #1 4'h0;
  else if (spi_clk_trig)
    sta_d <= #1 sta_d_nxt;
end

always @(sta_d or buf_rd_cnt or
         bwdl or bwdh or spi_cmd_sent or bwdt or cnt7)
begin
  case (sta_d)
  IDLE:
        if (spi_cmd_sent)
          sta_d_nxt = BEGIN;
        else
          sta_d_nxt = IDLE;
  BEGIN:
          sta_d_nxt = BUF_RD;

  BUF_RD:
        if ((buf_rd_cnt == bwdt)&&(cnt7==8'h07))
          sta_d_nxt = WAIT;
        else
          sta_d_nxt = BUF_RD;
  WAIT:
          sta_d_nxt = IDLE ;
        
  default:
          sta_d_nxt = IDLE;
  endcase
end


always @(posedge mcu_clk or negedge reset_n)
begin
  if (!reset_n)
    buf_rd_cnt <= #1 16'h0000;
  else if (!reset_s)
    buf_rd_cnt <= #1 16'h0000;
  else if (spi_clk_trig && buf_rd)
    buf_rd_cnt <= #1 buf_rd_cnt + 1'b1;
  else if (spi_clk_trig && (sta_d == WAIT))
    buf_rd_cnt <= #1 16'h0000;
end



assign xmit_done = (xmit_cnt == bitl) ;

always @(posedge mcu_clk or negedge reset_n)
begin
  if (!reset_n)
    xmit_done_d1 <= #1 1'b0;
  else if (!reset_s)
    xmit_done_d1 <= #1 1'b0;
  else if (spi_clk_trig)
    xmit_done_d1 <= #1 xmit_done;
end

always @(posedge mcu_clk or negedge reset_n)
begin
  if (!reset_n)
    xmit_cnt <= #1 8'h00;
  else if ((spi_clk_trig && xmit_done) || !reset_s)
    xmit_cnt <= #1 8'h00;
  else if (spi_clk_trig && (state == XMIT))
    xmit_cnt <= #1 xmit_cnt + 1'b1;
end

assign xmit_nxt = xmit_nxt_dat;

always @(posedge mcu_clk or negedge reset_n)
begin
  if (!reset_n)
    xmit_nxt_dat <= #1 1'b0;
  else if (!reset_s)
    xmit_nxt_dat <= #1 1'b0;
  else if (spi_clk_trig && (buf_rd_cnt == bwdt) && (cnt7 == 8'h7))
    xmit_nxt_dat <= #1 1'b0;
  else if (spi_clk_trig && buf_rd)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -