搜索
bottom↓
回复: 16

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

[复制链接]

出0入0汤圆

发表于 2011-7-6 17:58:56 | 显示全部楼层 |阅读模式
/****************************************************************
模块名称: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

//希望大家多多指点^

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2011-7-7 09:23:53 | 显示全部楼层
哈,放假前写了个iic的,不过调试ch452的时候没调出来,等成功了我也贴贴。

出0入0汤圆

发表于 2011-7-7 10:47:19 | 显示全部楼层
调试过没啊!也准备搞搞SPI。。。。。。

出0入0汤圆

 楼主| 发表于 2011-7-7 13:46:31 | 显示全部楼层
回复【1楼】brahen
-----------------------------------------------------------------------

呵呵 互相学习嘛……

出0入0汤圆

发表于 2011-7-7 17:55:24 | 显示全部楼层
从设备模块中只有一个CLK 难道SPI 的CLK 用来做系统时钟?
最难的 是 两个系统时钟间的跨越。

出0入0汤圆

 楼主| 发表于 2011-7-8 12:35:56 | 显示全部楼层
回复【4楼】mcupro 李伟
-----------------------------------------------------------------------
恩  主机模块 和 从机公用一个同步时钟,但主机有一个单独的时钟用以控制时序动作,调试过了 没有什么影响。呵呵

出0入0汤圆

发表于 2011-7-8 23:43:04 | 显示全部楼层
回复【5楼】ZISONM
回复【4楼】mcupro 李伟
-----------------------------------------------------------------------
恩  主机模块 和 从机公用一个同步时钟,但主机有一个单独的时钟用以控制时序动作,调试过了 没有什么影响。呵呵
-----------------------------------------------------------------------

恩 不错 :)

出0入0汤圆

发表于 2011-7-10 22:15:16 | 显示全部楼层
回复【楼主位】ZISONM
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2011-7-10 22:30:11 | 显示全部楼层
这个不错,适合初学者

出0入0汤圆

发表于 2011-7-16 09:36:53 | 显示全部楼层
时钟太乱了,clk上下降沿都使用,工程大了,容易出问题,timing也不好分析

出0入0汤圆

发表于 2011-7-16 09:41:06 | 显示全部楼层
许多地方也没有用reset信号,信号在初始时给个初始信号会比较好

出0入0汤圆

发表于 2011-7-17 13:32:15 | 显示全部楼层
回复【8楼】monkhooder
-----------------------------------------------------------------------

值得学习啊!哈哈。

出0入0汤圆

发表于 2011-7-22 10:42:12 | 显示全部楼层
刚好正要做这个,学习下

出0入0汤圆

发表于 2011-10-14 11:38:55 | 显示全部楼层
回复【楼主位】ZISONM
-----------------------------------------------------------------------

好,就要用这个,谢谢了!

出0入0汤圆

发表于 2011-10-20 17:10:47 | 显示全部楼层
收藏了。多谢分享

出0入0汤圆

发表于 2011-10-21 11:38:37 | 显示全部楼层
altera有标准模块。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 13:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表