yl604922959 发表于 2010-10-28 09:45:26

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

`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 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 cnt;        //cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间
reg 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 device_add;        //最低bit:1--读,0--写
parameter device_read = 8'b1010_0001;
parameter device_write = 8'b1010_0000;
reg byte_add;        // 写入地址
reg byte_data1;        //写入的数据
reg        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 current_state,next_state;
reg sda_r,sda_link;        //输出数据寄存器
reg 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;
                                                        end
                                                else if(cnt==3'd0) begin
                                                        device_add <= {device_add,device_add};
                                                        end
                                               end
                                        else if((num==4'd8) && (cnt==3'd3)) begin       
                                                device_add <= {device_add,device_add};//
                                                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;
                                                        end
                                                else if(cnt==3'd0) begin
                                                        byte_add <= {byte_add,byte_add};
                                                        end
                                               end
                                        else if((num==4'd8) &&        (cnt==3'd3)) begin
                                                byte_add <= {byte_add,byte_add};//       
                                                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)
                                                        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;
                                                        end
                                                else if(cnt==3'd0) begin
                                                        device_add <= {device_add,device_add};
                                                        end
                                               end
                                        else if((num==4'd8) && (cnt==3'd3)) begin
                                                device_add <= {device_add,device_add};
                                                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 <= sda;
                                                                        end
                                                                else if(cnt==3'd2) begin
                                                                        byte_data2 <= {byte_data2,byte_data2};
                                                                       end
                                                                end
                                                        else if((cnt==3'd3) && (num==4'd8)) begin
                                                                byte_data2 <= {byte_data2,byte_data2};
                                                                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;
                                                                        end
                                                                else if(cnt==3'd0) begin
                                                                        byte_data1 <= {byte_data1,byte_data1};
                                                                        end
                                                               end
                                                        else if((cnt==3'd3) && (num==4'd8)) begin
                                                                byte_data1 <= {byte_data1,byte_data1};
                                                                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;

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

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

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

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

task write_data begin        //写数据任务
        case (num)
                4'd0:        sda_r <= byte_data1;
                4'd1: sda_r <= byte_data1;
                4'd2: sda_r <= byte_data1;
                4'd3: sda_r <= byte_data1;
                4'd4: sda_r <= byte_data1;
                4'd5: sda_r <= byte_data1;
                4'd6: sda_r <= byte_data1;
                4'd7: sda_r <= byte_data1;
                default: ;
                endcase
        end
endtask

task read_data begin        //写数据任务
        case (num)
                4'd0:        byte_data2 <= sda;
                4'd1: byte_data2 <= sda;
                4'd2: byte_data2 <= sda;
                4'd3: byte_data2 <= sda;
                4'd4: byte_data2 <= sda;
                4'd5: byte_data2 <= sda;
                4'd6: byte_data2 <= sda;
                4'd7: byte_data2 <= sda;
                default: ;
                endcase
        end
endtask

endmodule

yl604922959 发表于 2010-10-28 09:47:00

呃,示波器上看只有sda在动,但是scl根本就没有反应,这是怎么回事呢?
开发环境:ise8.2
页: [1]
查看完整版本: verilog iic 求助,程序中的scl示波器上看是没有反应的...