SPI通信---verilog(全双工)

    做一个全双工的通信方式,可以一边发送一边接收,速度会快,但是感觉实用性不大。根据具体的情况再做修改吧。

   读取结果没有引出,输入地址也没有引出,在程序中固化了。

  程序:

    

 
    /********************************Copyright**************************************                           
    **----------------------------File information--------------------------
    ** File name  :spi_main_2.v  
    ** CreateDate :2015.04
    ** Funtions   : SPI作为主机的全双工模式,一边发送地址数据一边接收数据
    ** Operate on :M5C06N3L114C7
    ** Copyright  :All rights reserved. 
    ** Version    :V1.0
    **---------------------------Modify the file information----------------
    ** Modified by   :
    ** Modified data :        
    ** Modify Content:
    *******************************************************************************/
   
     module  spi_main_2  (
                                     clk,
                                     rst_n,
                                                               
                                    txd_rd_en,
                                    
                                    spi_cs,
                                    spi_sck,
                                    spi_miso,
                                    spi_mosi
                 );
     input          clk;
     input          rst_n;
     
     input          txd_rd_en;
     
     output    reg     spi_cs;
     output    reg     spi_sck;
     output    reg     spi_mosi;
     input             spi_miso;
     
     `define    addr_1    8'h01 
     `define    addr_2    8'h02 
     `define    addr_3    8'h03 
     //---------------------------
       reg  [3:0]     state;
         reg            txd_en;
         reg  [7:0]     rxd_data_1;
         reg  [7:0]     rxd_data_2;
         reg  [7:0]     rxd_data_3;
         reg            txd_over;
         reg  [7:0]     txd_data_reg;
         reg  [7:0]     rxd_data_shift;
        always @(posedge clk or negedge rst_n)
         begin
          if(!rst_n)
           begin
              state <= 0;
                    txd_en<= 0;
                    rxd_data_1 <= 0;
                    rxd_data_2 <= 0;
                    rxd_data_3 <= 0;
                    spi_cs <= 1;
                    txd_data_reg <= 8'd0;
            end
          else 
            begin
              case(state)
                     'd0:
                       begin
                           txd_en<= 0;
                             spi_cs <= 1;
                             txd_data_reg <= 8'd0;
                             if(txd_rd_en)
                                 state <= 'd1;
                            end
                    'd1:
                      begin
                             spi_cs <= 0;    
                             state <= 'd2;    
                            end
                    'd2:
                      begin
                            if(txd_over)
                             begin
                                  txd_data_reg <= 8'h00;
                                    txd_en<= 0;     
                                  state <= 'd3;        
                                end
                            else 
                              begin
                                    txd_data_reg <= `addr_1;
                                    txd_en<= 1;
                                 end
                        end
                    'd3:
                      begin
                                if(txd_over)
                             begin
                                  txd_data_reg <= 8'h00;
                                    txd_en<= 0;     
                                  state <= 'd4;    
                                    rxd_data_1 <= rxd_data_shift;
                                end
                            else 
                              begin
                                    txd_data_reg <= `addr_2;
                                    txd_en<= 1;
                                 end                                
                         end
                    'd4:
                      begin
                                if(txd_over)
                             begin
                                  txd_data_reg <= 8'h00;
                                    txd_en<= 0;     
                                  state <= 'd5;    
                                    rxd_data_2 <= rxd_data_shift;
                                end
                            else 
                              begin
                                    txd_data_reg <= `addr_3;
                                    txd_en<= 1;
                                 end                                
                         end    
                    'd5:
                      begin
                                if(txd_over)
                             begin
                                  txd_data_reg <= 8'h00;
                                    txd_en<= 0;     
                                  state <= 'd6;    
                                    rxd_data_3 <= rxd_data_shift;
                                end
                            else 
                              begin
                                    txd_data_reg <= 8'h00;
                                    txd_en<= 1;
                                 end                                
                         end    
                    'd6:
                       begin
                         spi_cs <= 1;    
                             state <= 'd0;
                          end
                    default :    state <= 'd0; 
                endcase                                  
         end
     end
      
    //----------------------------
       reg   [3:0]   state_bit;
         reg   [3:0]   cnt;
    always @(posedge clk or negedge rst_n)
     begin
      if(!rst_n)
       begin
        spi_sck <= 0;
            spi_mosi <= 0;
            state_bit <= 0;
            cnt <= 0;
            rxd_data_shift <= 0;
            txd_over <= 0;
        end
      else if(txd_en)
        begin
         case(state_bit) 
                'd0:
                  begin
                        spi_sck <= 0;
                  spi_mosi <= 0;
                        state_bit <= 'd1;
                        cnt <= 0;
                        rxd_data_shift <= 0;
                     end
                'd1:
                  begin
                            spi_mosi <= txd_data_reg[7-cnt[2:0]];  /* 先发送最高位 */
                            state_bit <= 'd2;
                     end
                'd2:
                  begin
                          spi_sck <= 1;                          
                         state_bit <= 'd3;
                     end
                'd3:
                  begin
                        cnt <= cnt + 1;    
                        state_bit <= 'd4;    
                     end
                'd4:
                  begin
                        spi_sck <= 0;    
                        state_bit <= 'd5;        
                     end
                'd5:
                  begin
                        rxd_data_shift[0]    <= spi_miso;
                        if(cnt == 8)
                          begin
                            cnt <= 0;
                            state_bit <= 'd7;    
                                
                             end
                         else 
                               state_bit <= 'd6;    
                    end
                'd6:
                   begin
                            state_bit <= 'd1;     
                          rxd_data_shift <=     rxd_data_shift << 1;
                        end
                'd7:
                  begin
                        txd_over <= 1;
                        state_bit <= 'd8;                                
                     end
                'd8:
                  begin
                        txd_over <= 0;
                        state_bit <= 'd8;    
                     end
                 default:state_bit <= 'd0;    
            endcase           
      end
    else 
            begin
                    spi_sck <= 0;
                    spi_mosi <= 0;
                    state_bit <= 0;
                    cnt <= 0;
                    rxd_data_shift <= 0;
                    txd_over <= 0;
        end
 end
        
        
    endmodule
    
    
View Code

 

 测试程序:

   

/********************************Copyright**************************************                           
**----------------------------File information--------------------------
** File name  :api_main_tb.v  
** CreateDate :2015.04
** Funtions   : 测试文件
** Operate on :M5C06N3L114C7
** Copyright  :All rights reserved. 
** Version    :V1.0
**---------------------------Modify the file information----------------
** Modified by   :
** Modified data :        
** Modify Content:
*******************************************************************************/
 
  module  api_main_tb;
     reg             clk;
     reg             rst_n;
     
     reg             txd_rd_en;
     
     wire            spi_cs;
     wire            spi_sck;
     wire            spi_mosi;
     reg             spi_miso;
     
   spi_main_2  spi_main_2_1(
                                     .clk,
                                     .rst_n,
                                                               
                                    .txd_rd_en,
                                    
                                    .spi_cs,
                                    .spi_sck,
                                    .spi_miso,
                                    .spi_mosi
                         );

      parameter tck = 24;
     parameter t = 1000/tck;
     
     always 
       #(t/2) clk = ~clk;
    
     
     always 
            #(t*2) spi_miso = ~spi_miso;
    
    initial 
      begin
       clk= 0;
         rst_n = 0;
         spi_miso = 0;
         txd_rd_en = 0;
         
       #(5*t)   rst_n = 1;
          
            #(2*t) txd_rd_en = 1;
         #(2*t) txd_rd_en = 0;
         
         
      end
endmodule
View Code

仿真图:

 

posted @ 2015-04-16 14:08  远航路上ing  阅读(2020)  评论(0编辑  收藏  举报