📄 spi_core_slave.v
字号:
//=============================================================================// Revision // woong chul IM// 2009.02.27//=============================================================================module spi_core_slave ( i_spi_en, i_spi_cse, // select [active low] i_spi_clk, // spi clock [data change rising / capture falling] i_spi_sdi, // serial data in o_spi_sdo, // serial data out i_nreset, i_sclk, o_addr, // Receive_address , TRansmit_address o_rdat_rx_wen, // Receive_data write enable with address output o_rdat_rx, // Receive_data o_tdat_tx_req, // TRansmit_data read request with address output i_tdat_input_en, // TRansmit_data input enble with data i_tdat_tx_rdat, // TRansmit_data o_done , // TRANSFER or RECEIVE completed o_busy, // spi block is in busy o_error ); // R/W 囱赁释 0: Transfer(READ) 1: receive data(WRITE) //------------------------------------// ### in/out port declaration ###//------------------------------------input i_spi_en; input i_nreset;input i_sclk;input i_spi_cse;input i_spi_clk;input i_spi_sdi;output o_spi_sdo;output [7:0] o_addr;output [7:0] o_rdat_rx;output o_rdat_rx_wen; output o_tdat_tx_req;input [7:0] i_tdat_tx_rdat; input i_tdat_input_en;// output [ 2:0] o_C_ST; output o_done;output o_busy; output o_error;//------------------------------------// ### in/out signal declaration ###//------------------------------------wire i_nreset; // system reset, active lowwire i_sclk; // system clockwire i_spi_cse; // chip selection from external device reg d_spi_cse;wire i_spi_clk; // spi clock from external devicewire i_spi_sdi; // spi serial data from external devicereg o_spi_sdo; // spi serial data to external device wire i_spi_en; // 0 : spi disable, 1 : spi enable ( r_bit_cnt count , chanege stat) reg [7:0] o_addr; // RX address freg [7:0] o_rdat_rx; // RX data OUT fwire o_rdat_rx_wen; // enable to write data with address outputwire [7:0] i_tdat_tx_rdat; // TX data INreg [7:0] r_tdat_tx_rdat;wire [ 2:0] o_C_ST; // current state . wire o_done;wire i_tdat_input_en; // enable to read TX _data from regreg o_tdat_tx_req; // request signal to get TX_data reg TX_RX_NST_info; // TXDATA / RXDATA information//------------------------------------// ### internal signal declaration ###//------------------------------------reg [ 2:0] C_ST, N_ST;reg [ 2:0] r_bit_cnt;wire w_iclk;reg r_iclk;wire w_chg_en;wire w_cap_en; wire w_sl_str;reg r_sl_str;wire w_sl_str_sync;wire w_sl_end_sync;reg r_state_str;//reg r_tdat_tx_done;reg r_rdat_rx_done;reg r_addr_rx_done; reg r_number_rx_done ;reg [7:0] r_p2s_tdat_reg;reg [7:0] r_s2p_addr_reg;reg [7:0] r_s2p_number_reg;reg [7:0] r_s2p_rdat_reg;reg [7:0] r_sl_word_no;reg [7:0] r_sl_word_no2;wire w_DBurst_en;reg d_r_rdat_rx_done;reg [7:0] r_number_rx; reg [7:0] r_addr_rx;//////////////////////reg r_done ;reg r_error ;///////////////////////------------------------------------// ### internal signal declaration ###//------------------------------------parameter [ 2:0] IDLE = 3'b000, ADDR = 3'b001, NUMBER = 3'b010, TXDATA = 3'b011, RXDATA = 3'b100, DONE = 3'b101; // assign o_C_ST = C_ST;//============================================================================= //-------------------------------------------// Parameter//------------------------------------------- parameter p_spi_dir = 1'b1 ; // spi_cse, spi_clk direction // 0 : master mode (out), 1 : slave mode (in)parameter p_idle_en = 1'b1; // 0 : spi_clk idle disable, // 1 : spi_clk idle enable// parameter p_idl_pol = 1'b0; // 0 : if idle state, spi_clk is " LOW " (MASTER option) // 1 : if idle state, spi clk is " HIGH "parameter p_clk_pha = 1'b1; // 0 : data change falling / capture rising // 1 : data change rising / capture fallingparameter p_cse_pol = 1'b1; // 0 : active " HIGH ", 1 : active " LOW " parameter p_intr_en = 1'b1 ; // 0 : interrupt disable, 1 : interrupt enable// assign p_lsb_first = 1'b0 ; // 0 : msb first, 1 : lsb first <-- msb first operation (fixed )//assign i_spi_en = 1'b1 ; // 0 : spi disable, 1 : spi enable <-- given by external input parameter p_addr_wth = 3'b111; // address length : 1 ~ 32 bitsparameter p_dat_wth = 3'b111; // tx/rx data length : 1 ~ 32 bitsparameter p_number_wth = 3'b111; // rx data length : 1 ~ 32 bits //--------------------------------------------// ### Internal used spi clock ###//--------------------------------------------assign w_iclk = i_spi_clk ; always @(posedge i_sclk or negedge i_nreset) begin if (!i_nreset) r_iclk <= 1'b0; else r_iclk <= w_iclk;end //**************************************************//--------------------------------------------// ### Data change / capture enable signal ###//--------------------------------------------assign w_chg_en = p_clk_pha ? ( w_iclk && ~r_iclk) : (~w_iclk && r_iclk);assign w_cap_en = p_clk_pha ? (~w_iclk && r_iclk) : ( w_iclk && ~r_iclk); //--------------------------------------------// ### Slave start enable signal ###//--------------------------------------------assign w_sl_str = (p_cse_pol ^ i_spi_cse) ? 1'b1 : 1'b0;always @(posedge i_sclk or negedge i_nreset) begin if(!i_nreset) r_sl_str <= 1'b0; else r_sl_str <= w_sl_str;endassign w_sl_str_sync = (w_sl_str && ~r_sl_str) ? 1'b1 : 1'b0;assign w_sl_end_sync = (~w_sl_str && r_sl_str) ? 1'b1 : 1'b0; //--------------------------------------------// ### Number, Addr, Data port bit counter ###//--------------------------------------------always @(posedge i_sclk or negedge i_nreset) begin if(!i_nreset) r_bit_cnt <= 3'b0; else if( i_spi_cse== p_cse_pol ) r_bit_cnt <= 3'b0; else if(i_spi_en && w_chg_en) begin if( ((C_ST == ADDR) && (r_bit_cnt == p_addr_wth)) || ((C_ST == TXDATA) && (r_bit_cnt == p_dat_wth)) || ((C_ST == RXDATA) && (r_bit_cnt == p_dat_wth)) || ((C_ST == NUMBER) && (r_bit_cnt == p_number_wth)) || ((C_ST == IDLE) || (C_ST == DONE)) ) r_bit_cnt <= 3'b0; else r_bit_cnt <= r_bit_cnt + 1'h1; end else r_bit_cnt <= r_bit_cnt;end //------------------------------------------//### BURST COUNT & ADDRESS OUT ###//------------------------------------------always @(posedge i_sclk or negedge i_nreset) begin if(!i_nreset) begin r_sl_word_no <= 8'b0; r_sl_word_no2 <= 8'b0; end else begin if ((C_ST == RXDATA) |(C_ST == TXDATA)) if ( (r_bit_cnt == p_dat_wth) && (r_sl_word_no < r_number_rx) && w_chg_en ) r_sl_word_no <= r_sl_word_no + 1'b1; else r_sl_word_no <= r_sl_word_no; else r_sl_word_no <= 8'b0 ; if (C_ST == TXDATA) if((r_bit_cnt == 4'b0001) && (r_sl_word_no2 < r_number_rx) && w_chg_en ) r_sl_word_no2 <= r_sl_word_no2 + 1'b1; else r_sl_word_no2 <= r_sl_word_no2; else r_sl_word_no2 <= 8'b0 ; end end//--------------------------------------------// ### State Machine start signal for M/S ###//--------------------------------------------always @(w_sl_str) begin r_state_str <= w_sl_str; end //------------------------------------------// ### STATE MACHINE ###//------------------------------------------//------------------------------------------//CURRENT STATEalways @(posedge i_sclk or negedge i_nreset) begin if(!i_nreset) C_ST <= IDLE; else if ( ( i_spi_cse== p_cse_pol ) ) C_ST <= IDLE; else if(i_spi_en) if(w_chg_en || w_sl_str_sync || w_sl_end_sync ) C_ST <= N_ST; else C_ST <= C_ST; else C_ST <= IDLE;end //----------------------------------------//NEXT STATE always @(C_ST or r_state_str or r_bit_cnt or r_sl_word_no or r_number_rx or r_s2p_number_reg or i_spi_cse or TX_RX_NST_info) begin case (C_ST) IDLE : if(r_state_str) N_ST <= ADDR; else N_ST <= IDLE; ADDR : if(r_bit_cnt == p_addr_wth)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -