在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 3439|回复: 7

[原创] 今天刚写了一个SPI的收发模块,恳请大家多多给予批评指点,不胜感激……

[复制链接]
发表于 2011-7-6 17:58:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
/****************************************************************
模块名称:SPI 主发送模块       
模块功能:用于串行接发数据,一共分四个管脚,同步时钟管脚、数据发
送端、数据接收端、片选端。发送时,高位在前低位在后,全双工、上
升沿发送数据,下降沿接收数据。
******************************************************************/
module SPI (         reset_n,sclk,clk , mosi, ss ,miso,data_out );
                               
        parameter WIDE=8;                                                                                        //发送数据的位宽
       
        parameter[8:0]  S0=9'd0, S1=9'd1, S2=9'd2, S3=9'd4, S4=9'd8,
                                         S5=9'd16, S6=9'd32, S7=9'd64, S8=9'd128;
                                         
        parameter[8:0]  R0=9'd0, R1=9'd1, R2=9'd2, R3=9'd4, R4=9'd8,
                                         R5=9'd16, R6=9'd32, R7=9'd64, R8=9'd128;
       
       
       
        input                 sclk,miso,reset_n;
        output         reg        mosi,clk,ss;
        output                [WIDE-1:0 ]data_out;       
        reg                 [WIDE-1:0 ]s_data=8'B11010101,r_data;                                                //待发送数据寄存器
        reg                        [WIDE:0 ] cs_send,ns_send,cs_rec,ns_rec;

/*******************************************************/       
        always @ ( posedge sclk )
                begin
                        if(!reset_n)                                                        //允许收发
                                begin
                                        ss<=1'b1;
                                        clk<=1'b0;
                                end
                        else
                                begin
                                        clk<=~clk;
                                        ss<=1'b0;
                                end
                end
               
/*---------------------接收数据---------------------------                */       

        always @ ( posedge clk )                                //上升沿 发送数据
                begin
                        if(!ss)
                                begin
                                        cs_send<=ns_send;                                       
                                end
                        else cs_send<=S0;
                end
               
/*---------------------接收数据---------------------------                */       
                       
        always @ ( negedge clk )                                //上升沿 发送数据
                begin
                        if(!ss)
                                begin
                                        cs_rec<=ns_rec;                                       
                                end
                        else cs_rec<=R0;
                end
               
/*--------------发送状态变换---------------------------------*/       
        always @ (cs_send)
                begin
                        if(!ss)
                                case(cs_send)
                                        S0:ns_send=S1;
                                        S1:ns_send=S2;
                                        S2:ns_send=S3;
                                        S3:ns_send=S4;
                                        S4:ns_send=S5;
                                        S5:ns_send=S6;
                                        S6:ns_send=S7;
                                        S7:ns_send=S8;
                                        S8:ns_send=S0;
                                        default:ns_send=S0;
                                endcase
                        else ns_send=S0;
                end
               
/*---------------------发送数据输出---------------------------*/               

        always @ (posedge clk)
                begin
                        if(!ss)
                                case(ns_send)
                                        S1:mosi<=s_data[WIDE-1];
                                        S2:mosi<=s_data[WIDE-2];
                                        S3:mosi<=s_data[WIDE-3];
                                        S4:mosi<=s_data[WIDE-4];
                                        S5:mosi<=s_data[WIDE-5];
                                        S6:mosi<=s_data[WIDE-6];
                                        S7:mosi<=s_data[WIDE-7];
                                        S8:mosi<=s_data[WIDE-8];
                                endcase
                end  
/*--------------接收状态变换---------------------------------*/       
        always @ (cs_rec)
                begin
                        if(!ss)
                                case(cs_rec)
                                        R0:ns_rec=R1;
                                        R1:ns_rec=R2;
                                        R2:ns_rec=R3;
                                        R3:ns_rec=R4;
                                        R4:ns_rec=R5;
                                        R5:ns_rec=R6;
                                        R6:ns_rec=R7;
                                        R7:ns_rec=R8;
                                        R8:ns_rec=R0;
                                        default:ns_rec=R0;
                                endcase
                        else ns_rec=R0;
                end       
                                       
/*--------------------导入接收数据---------------------------*/               
               
        always @ (negedge clk)
                begin
                        if(!ss)
                                case(ns_rec)
                                        R1:r_data[WIDE-1]<=miso;
                                        R2:r_data[WIDE-2]<=miso;
                                        R3:r_data[WIDE-3]<=miso;
                                        R4:r_data[WIDE-4]<=miso;
                                        R5:r_data[WIDE-5]<=miso;
                                        R6:r_data[WIDE-6]<=miso;
                                        R7:r_data[WIDE-7]<=miso;
                                        R8:r_data[WIDE-8]<=miso;
                                endcase
                end
        assign data_out = r_data;
endmodule                
                               
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
       
//------------------------------------------------------下面是从机模块------------------------------------------------------------------------------------------

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------


/****************************************************************
模块名称:SPI2 从机模块
模块功能:用于串行接发数据,一共分四个管脚,同步时钟管脚、数据发
送端、数据接收端、片选端。发送时,高位在前低位在后,全双工、上
升沿发送数据,下降沿接收数据。
******************************************************************/
module SPI2 (   clk , miso, ss ,mosi, data);
    parameter WIDE=8;                       //发送数据的位宽
    parameter   T0=9'd0,T1=9'd1,T2=9'd2,T3=9'd4,T4=9'd8,T5=9'd16,
                T6=9'd32,T7=9'd64,T8=9'd128;
    parameter   R0=9'd0,R1=9'd1,R2=9'd2,R3=9'd4,R4=9'd8,R5=9'd16,
                R6=9'd32,R7=9'd64,R8=9'd128;
    input clk,miso,ss;
    output mosi;
    reg  mosi_r;
    reg [WIDE-1:0 ]t_data=8'B10001111,r_data;           //待发送数据寄存器
    reg [8:0]state_send,next_state;
    reg [8:0] state_recive,next_rec;
   output wire [WIDE-1:0 ]data;
/*------------------------状态转换模块----------------------------*/

    always @ (posedge clk)
        begin
            if(!ss)
                state_send<=next_state;
            else
                state_send<=T0;
        end
        
    always @ (negedge clk )
        begin
            if(!ss)
                state_recive<=next_rec;
            else
                state_recive<=R0;
        end
               

        
/*---------------------send数据---------------------------*/   

    always @ (state_send )             //上升沿 发送数据
        begin
                        if(!ss)
                        begin
                                case(state_send)
                                        T0:next_state=T1;
                                        T1:next_state=T2;
                                        T2:next_state=T3;
                                        T3:next_state=T4;
                                        T4:next_state=T5;
                                        T5:next_state=T6;
                                        T6:next_state=T7;
                                        T7:next_state=T8;
                                        T8:next_state=T0;
                                default:next_state=T0;              
                                endcase
                        end
                        else         next_state=T0;
        end
        
        
always @ ( posedge clk  )             //上升沿 发送数据
        begin
                        if(!ss)
                        begin
            case(next_state)
            T1: begin
                mosi_r<=t_data[WIDE-1];
                end
            T2: begin
                mosi_r=t_data[WIDE-2];
                end
            T3: begin
                mosi_r<=t_data[WIDE-3];
                end
            T4: begin
                mosi_r<=t_data[WIDE-4];
                end
            T5: begin
                mosi_r<=t_data[WIDE-5];
                end
            T6: begin
                mosi_r<=t_data[WIDE-6];
                end
            T7: begin
                mosi_r<=t_data[WIDE-7];
                end
            T8: begin
                mosi_r<=t_data[WIDE-8];
                end         
                        endcase
        end
    end
      assign mosi=mosi_r;
        
/*---------------------接收数据---------------------------*/   

    always @ (state_recive)
        begin
                        if(!ss)
                        begin
                                case(state_recive)
                                R0:next_rec=R1;
                                R1: begin
                                        next_rec=R2;
                                        end
                                R2: begin
                                        next_rec=R3;
                                        end
                                R3: begin
                                   next_rec=R4;
                                        end
                                R4: begin
                                   next_rec=R5;
                                        end
                                R5: begin
                                        next_rec=R6;
                                        end
                                R6: begin
                                        next_rec=R7;
                                        end
                                R7: begin
                                        next_rec=R8;
                                        end
                                R8: begin
                                        next_rec=R0;
                                        end
                        default:next_rec=R0;
                        endcase
                        end
        else next_rec=R0;
      end   
        
always @ (negedge clk)
        begin
                        if(!ss)
            case(next_rec)
            R1: begin
                r_data[WIDE-1]<=miso;
                end
            R2: begin
                r_data[WIDE-2]<=miso;
                end
            R3: begin
                r_data[WIDE-3]<=miso;
                end
            R4: begin
                r_data[WIDE-4]<=miso;
                end
            R5: begin
                r_data[WIDE-5]<=miso;
                end
            R6: begin
                r_data[WIDE-6]<=miso;
                end
            R7: begin
                r_data[WIDE-7]<=miso;
                end
            R8: begin
                r_data[WIDE-8]<=miso;
                end
        endcase
        end
        
       assign data=r_data;
endmodule

//希望大家多多指点^
发表于 2011-7-27 16:24:38 | 显示全部楼层
顶楼主
我看SPI一段时间了,就是写不出来呀
发表于 2011-7-27 16:30:53 | 显示全部楼层
本帖最后由 418478935 于 2011-7-27 16:52 编辑

饿,看不懂
楼主你得master和slave都是用状态机写的吗?
发表于 2011-7-30 16:17:57 | 显示全部楼层




    楼主我用你得模块,自己写了testbench。
但是mosi 和 miso 一直都是 X。
难道是我的testbench写错了。
还麻烦你能不能贴下你得testbench。
发表于 2011-7-31 16:04:43 | 显示全部楼层
thanks!!!
发表于 2012-2-17 15:15:53 | 显示全部楼层
学习学习
发表于 2012-2-17 20:25:10 | 显示全部楼层
非常是不错的资料
发表于 2014-10-22 16:06:14 | 显示全部楼层
能借用吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-11 11:19 , Processed in 0.031527 second(s), 10 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表