搜索
bottom↓
回复: 1

verilog iic 求助,程序中的scl示波器上看是没有反应的...

[复制链接]

出0入0汤圆

发表于 2010-10-28 09:45:26 | 显示全部楼层 |阅读模式
`timescale 1ns / 1ps
module iic_top(clk,rst_n,sw1,sw2,scl,sda,led_d2,led_d3,led_d4,led_d5);

input clk;        // 4m
input rst_n;        //复位信号,低有效
input sw1,sw2;
output scl;        // 24C02的时钟端口
inout sda;        // 24C02的数据端口
output led_d2,led_d3,led_d4,led_d5;        //四个LED灯

//--------------------------------------------
                //按键检测
reg sw1_r,sw2_r;        //每20ms检测一次键值
reg[19:0] cnt_20ms;

always @ (posedge clk or negedge rst_n)
        if(!rst_n) cnt_20ms <= 20'd0;
        else cnt_20ms <= cnt_20ms+1'b1;

always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                sw1_r <= 1'b1;
                sw2_r <= 1'b1;
                end
        else if(cnt_20ms == 20'h0000f) begin  
                sw1_r <= sw1;
                sw2_r <= sw2;
                end

//---------------------------------------------
                //分频部分
reg[2:0] cnt;        //cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间
reg[12:0] cnt_delay;        //
reg scl_r;        //时钟脉冲寄存器

always @ (posedge clk)
        if(!rst_n) cnt_delay <= 13'd0;
        else if(cnt_delay==13'd400) cnt_delay <= 13'd0;        //产生iic所需要的时钟
        else cnt_delay <= cnt_delay+1'b1;

always @ (posedge clk ) begin
        if(!rst_n) cnt <= 2'd0;
        else begin
                case (cnt_delay)
                        13'd99:        cnt <= 3'd1;
                        13'd199:        cnt <= 3'd2;
                        13'd299:        cnt <= 3'd3;
                        13'd399:        cnt <= 3'd0;
                        default: cnt <= 3'd5;
                        endcase
                end
end

always @ (posedge clk) begin        //posedge clk or negedge rst_n
        if(!rst_n) scl_r <= 1'b0;
        else if(cnt==3'd0) scl_r <= 1'b1;
   else if(cnt==3'd2) scl_r <= 1'b0;
        else scl_r <= scl_r;
end

//assign scl = scl_r ? 1'b1:1'b0;        //产生iic所需要的时钟
assign scl=scl_r;
//---------------------------------------------
                //需要写入24C02的地址和数据

reg[7:0] device_add;        //最低bit:1--读,0--写
parameter device_read = 8'b1010_0001;
parameter device_write = 8'b1010_0000;
reg[7:0] byte_add;        // 写入地址
reg[7:0] byte_data1;        //写入的数据
reg[7:0]        byte_data2;        //读出的数据
//---------------------------------------------
                //读、写时序
parameter IDLE         = 12'b000000000001;
parameter START1         = 12'b000000000010;
parameter ADD1         = 12'b000000000100;
parameter ACK1         = 12'b000000001000;
parameter ADD2         = 12'b000000010000;
parameter ACK2         = 12'b000000100000;
parameter START2         = 12'b000001000000;
parameter ADD3         = 12'b000010000000;
parameter ACK3                = 12'b000100000000;
parameter DATA         = 12'b001000000000;
parameter ACK4                = 12'b010000000000;
parameter STOP         = 12'b100000000000;

reg[11:0] current_state,next_state;
reg sda_r,sda_link;        //输出数据寄存器
reg[3:0] num;
reg ack_bit;        //响应位寄存器

always @ (next_state or rst_n)  //posedge clk or negedge rst_n
        if(!rst_n) current_state <= IDLE;
        else current_state <= next_state;

always @ (posedge clk or negedge rst_n) begin          ////rst_n or current_state or sw1_r or sw2_r or cnt
        if(!rst_n) begin
                        next_state <= IDLE;
                        sda_r <= 1'b1;
                        sda_link <= 1'b0;
                        num <= 4'd0;
                        byte_data2 <= 8'b0000_0000;
                        ack_bit <= 1'b1;
                        byte_add <= 8'b0000_0001;        // 0地址
                        byte_data1 <= 8'b0001_1101;        //写入的数据,低四位1001
                        device_add <= 8'b0000_0000;
                end  
        else           
                case (current_state)
                        IDLE:        begin
                                        sda_link <= 1'b0;
                                        if((!sw1_r || !sw2_r) && cnt==3'd1) begin          
                                                device_add <= device_write;
                                                next_state <= START1;
                                                sda_link <= 1'b1;
                                                sda_r <= 1'b1;
                                                end
                                        else next_state <= IDLE;
                                end
                        START1: begin
                                        if(cnt==3'd1) begin
                                                sda_r <= 1'b0;
                                                next_state <= ADD1;
                                                num <= 4'd0;
                                                end
                                        else next_state <= START1;
                                end
                        ADD1:        begin
                                        if(num<=4'd7) begin
                                                next_state <= ADD1;
                                                if(cnt==3'd3) begin
                                                        num <= num+1'b1;
                                                        sda_r <= device_add[7];
                                                        end
                                                else if(cnt==3'd0) begin
                                                        device_add <= {device_add[6:0],device_add[7]};
                                                        end
                                                 end
                                        else if((num==4'd8) && (cnt==3'd3)) begin       
                                                device_add <= {device_add[6:0],device_add[7]};//
                                                num <= 4'd0;
                                                sda_link <= 1'b0;                //sda置为高阻态
                                                next_state <= ACK1;
                                                end
                                        else next_state <= ADD1;
                                end
                        ACK1:        begin
                                        if(cnt==3'd2) begin
                                                next_state <= ADD2;
                                                end                  
                                        else next_state <= ACK1;
                                end
                        ADD2:        begin
                                        if(num<=4'd7) begin
                                                next_state <= ADD2;
                                                if(cnt==3'd3) begin
                                                        sda_link <= 1'b1;
                                                        num <= num+1'b1;
                                                        sda_r <= byte_add[7];
                                                        end
                                                else if(cnt==3'd0) begin
                                                        byte_add <= {byte_add[6:0],byte_add[7]};
                                                        end
                                                 end
                                        else if((num==4'd8) &&        (cnt==3'd3)) begin
                                                byte_add <= {byte_add[6:0],byte_add[7]};//       
                                                num <= 4'd0;
                                                sda_link <= 1'b0;                //sda置为高阻态
                                                next_state <= ACK2;
                                                if(!sw1_r) device_add <= device_write;
                                                else if(!sw2_r) device_add <= device_read;
                                                end
                                        else next_state <= ADD2;                                       
                                end
                        ACK2:        begin
                                        if(cnt==3'd2) begin
                                                case (device_add[0])
                                                        1'b1:        next_state <= START2;        //读操作
                                                        1'b0: next_state <= DATA;         //写操作
                                                        default: ;
                                                        endcase
                                                end
                                        else next_state <= ACK2;
                                end
                        START2: begin
                                        if(cnt==3'd3) begin
                                                sda_link <= 1'b1;
                                                sda_r <= 1'b1;
                                                end
                                        else if(cnt==3'd1) begin
                                                sda_r <= 1'b0;
                                                next_state <= ADD3;
                                                end         
                                end
                        ADD3:        begin
                                        if(num<=4'd7) begin
                                                next_state <= ADD3;
                                                if(cnt==3'd3) begin
                                                        num <= num+1'b1;
                                                        sda_r <= device_add[7];
                                                        end
                                                else if(cnt==3'd0) begin
                                                        device_add <= {device_add[6:0],device_add[7]};
                                                        end
                                                 end
                                        else if((num==4'd8) && (cnt==3'd3)) begin
                                                device_add <= {device_add[6:0],device_add[7]};
                                                num <= 4'd0;
                                                sda_link <= 1'b0;                //sda_r置为高阻态
                                                next_state <= ACK3;
                                                end
                                        else next_state <= ADD3;
                                end
                        ACK3:        begin
                                        if(cnt==3'd3) begin
                                                next_state <= DATA;
                                                end
                                        else next_state <= ACK3;
                                end
                        DATA:        begin
                                                if(!sw2_r) begin         //读
                                                        if(num<=4'd7) begin
                                                                next_state  <= DATA;
                                                                if(cnt==3'd1) begin       
                                                                        num <= num+1'b1;
                                                                        byte_data2[7] <= sda;
                                                                        end
                                                                else if(cnt==3'd2) begin
                                                                        byte_data2 <= {byte_data2[6:0],byte_data2[7]};
                                                                         end
                                                                end
                                                        else if((cnt==3'd3) && (num==4'd8)) begin
                                                                byte_data2 <= {byte_data2[6:0],byte_data2[7]};
                                                                num <= 4'd0;
                                                                next_state <= ACK4;
                                                                end
                                                        else next_state <= DATA;
                                                end
                                        else begin        //写
                                                        if(num<=4'd7) begin
                                                                next_state <= DATA;
                                                                if(cnt==3'd3) begin
                                                                        sda_link <= 1'b1;       
                                                                        num <= num+1'b1;
                                                                        sda_r <= byte_data1[7];
                                                                        end
                                                                else if(cnt==3'd0) begin
                                                                        byte_data1 <= {byte_data1[6:0],byte_data1[7]};
                                                                        end
                                                                 end
                                                        else if((cnt==3'd3) && (num==4'd8)) begin
                                                                byte_data1 <= {byte_data1[6:0],byte_data1[7]};
                                                                num <= 4'd0;
                                                                sda_link <= 1'b0;                //sda置为高阻态
                                                                next_state <= ACK4;
                                                                end
                                                        else next_state <= DATA;
                                                end
                                end
                        ACK4: begin
                                        if(cnt==3'd3) begin
                                                sda_r <= 1'b0;
                                                sda_link <= 1'b1;
                                                next_state <= STOP;                                               
                                                end
                                        else next_state <= ACK4;
                                end
                        STOP:        begin
                                        if(cnt==3'd1) begin
                                                sda_r <= 1'b1;
                                                end
                                        else if((cnt==3'd3) && sda_link) sda_link <= 1'b0;
                                        if(cnt_20ms==20'hffff0) next_state <= IDLE;
                                        else next_state <= STOP;
                                end
                        default: ;
                        endcase
end

assign sda = sda_link ? sda_r:1'bz;
assign {led_d2,led_d3,led_d4,led_d5} = byte_data2[3:0];

//---------------------------------------------
                //任务

task write_add1        //写地址1任务
        case (num)
                4'd0:        sda_r <= device_write[7];
                4'd1: sda_r <= device_write[6];
                4'd2: sda_r <= device_write[5];
                4'd3: sda_r <= device_write[4];
                4'd4: sda_r <= device_write[3];
                4'd5: sda_r <= device_write[2];
                4'd6: sda_r <= device_write[1];
                4'd7: sda_r <= device_write[0];
                default: ;
                endcase
endtask

task write_add2 begin        //写地址2任务
        case (num)
                4'd0:        sda_r <= byte_add[7];
                4'd1: sda_r <= byte_add[6];
                4'd2: sda_r <= byte_add[5];
                4'd3: sda_r <= byte_add[4];
                4'd4: sda_r <= byte_add[3];
                4'd5: sda_r <= byte_add[2];
                4'd6: sda_r <= byte_add[1];
                4'd7: sda_r <= byte_add[0];
                default: ;
                endcase
        end
endtask

task write_add3 begin        //写地址3任务
        case (num)
                4'd0:        sda_r <= device_read[7];
                4'd1: sda_r <= device_read[6];
                4'd2: sda_r <= device_read[5];
                4'd3: sda_r <= device_read[4];
                4'd4: sda_r <= device_read[3];
                4'd5: sda_r <= device_read[2];
                4'd6: sda_r <= device_read[1];
                4'd7: sda_r <= device_read[0];
                default: ;
                endcase
        end
endtask

task write_data begin        //写数据任务
        case (num)
                4'd0:        sda_r <= byte_data1[7];
                4'd1: sda_r <= byte_data1[6];
                4'd2: sda_r <= byte_data1[5];
                4'd3: sda_r <= byte_data1[4];
                4'd4: sda_r <= byte_data1[3];
                4'd5: sda_r <= byte_data1[2];
                4'd6: sda_r <= byte_data1[1];
                4'd7: sda_r <= byte_data1[0];
                default: ;
                endcase
        end
endtask

task read_data begin        //写数据任务
        case (num)
                4'd0:        byte_data2[7] <= sda;
                4'd1: byte_data2[6] <= sda;
                4'd2: byte_data2[5] <= sda;
                4'd3: byte_data2[4] <= sda;
                4'd4: byte_data2[3] <= sda;
                4'd5: byte_data2[2] <= sda;
                4'd6: byte_data2[1] <= sda;
                4'd7: byte_data2[0] <= sda;
                default: ;
                endcase
        end
endtask

endmodule

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

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

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-7-24 17:32

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

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