Verilog 并行数据流转换为一种特殊串行数据流模块的设计

Verilog 并行数据流转换为一种特殊串行数据流模块的设计_第1张图片

模块M0

`timescale 1ns/100ps
`define clk_cyc    50
module sigdata(rst,data,sclk,ack);
input        ack;
output        rst;
output    [3:0]    data;
output        sclk;
reg        rst;
reg        sclk;
reg    [3:0]    data;

initial 
begin
    rst <= 1;
    #10rst=0;
    #(`clk_cyc*2+3)rst=1;

end
initial
begin
    sclk = 0;
    data = 0;
    #(`clk_cyc * 1000) $stop;
end
always #(`clk_cyc) sclk = ~sclk;
always @(posedge ack)
begin
    #(`clk_cyc/2+3) data = data+1;
end
endmodule
 

模块M1
module ptosda(rst,sclk,data,ack,scl,sda);
input         rst,sclk;
input    [3:0]    data;                //并行口数据输入
output        ack;                //请求新的转换数据
output        scl;                
output        sda;                //定义SDA为单向的串行输出
reg        ack;
reg        scl;
reg        link_sda;
reg        sdabuf;
reg    [3:0]    databuf;
reg    [7:0]    state;

assign    sda = link_sda?sdabuf:1'b0;        //link_sda控制sdabuf输出到串行总线上

parameter     ready    = 8'b0000_0000,
        start    = 8'b0000_0001,
        bit3    = 8'b0000_0010,
        bit2    = 8'b0000_0100,
        bit1    = 8'b0000_1000,
        bit0    = 8'b0001_0000,
        prestop    = 8'b0010_0000,
        stop    = 8'b0100_0000,
        idle    = 8'b1000_0000;

always@(posedge sclk or negedge rst)        //由输入的sclk产生串行输出时钟scl
begin
    if(!rst)
        scl <= 1;
    else
        scl <= ~scl;
end    
always @(posedge ack)                //请求新数据时存入并行总线上要转换的数据
    databuf <= data;

/*主状态机:产生控制信号,根据databuf中保存的数据,按照协议产生sda串行信号*/
always @(negedge sclk or negedge rst)
    if(!rst)
    begin
        link_sda <= 0;            //把sdabuf与sda串行总线断开
        state     <= ready;
        sdabuf     <= 1;
        ack     <= 0;
    end
    else
    begin
        case(state)
            ready:
                if(ack)
                begin
                    link_sda <= 1;
                    state     <= start;
                end
                else
                begin
                    link_sda <= 0;
                    state    <= ready;
                    ack    <= 1;        //请求新数据信号置为1
                end
            start:
                if(ack&&scl)
                begin
                    sdabuf    <= 0;
                    state    <= bit3;
                end
                else
                begin
                    state    <= start;
                end
            bit3:
                if(!scl)
                begin
                    sdabuf    <= data[3];
                    state    <= bit2;
                    ack    <= 0;
                end
                else
                    state    <= bit3;
            bit2:
                if(!scl)
                begin
                    sdabuf    <= data[2];
                    state    <= bit1;
                end
                else
                    state    <= bit2;
            bit1:
                if(!scl)
                begin
                    sdabuf    <= data[1];
                    state    <= bit0;
                end
                else
                    state    <= bit1;
            bit0:
                if(!scl)
                begin
                    sdabuf    <= data[0];
                    state    <= prestop;
                end
                else
                    state    <= bit0;
            prestop:
                if(!scl)
                begin
                    sdabuf    <= 0;
                    state    <= stop;
                end
                else
                    state    <= prestop;
            stop:
                if(scl)
                begin
                    sdabuf    <= 1;
                    state    <= idle;
                end
                else
                    state    <=stop;
            idle:
                begin
                    link_sda<= 0;
                    state    <= ready;
                end
            default:
                begin
                    link_sda<= 0;
                    sdabuf  <= 1;
                    state    <= ready;
                end
        endcase
    end
sigdata u0(.rst(rst),.data(data),.sclk(sclk),.ack(ack));
endmodule

模块M2

module out16hign(scl,sda,outhigh);
input         scl;
input         sda;
output    [15:0]     outhigh;
reg    [5:0]    mstate;                //本模块的主状态
reg    [3:0]    pdata,pdatabuf;            //用寄存器和最终数据寄存器记录串行数据位。
reg    [15:0]    outhigh;            //输出位寄存器

reg        Startflag,Endflag;        //数据开始和结束标记
always@(negedge sda)
begin
    if(scl)
        Startflag <= 1;
    else if(Endflag)
        Startflag <= 0;
end

always@(posedge sda)
    if (scl)
    begin
        Endflag <= 1;
        pdatabuf<= pdata;        //把收到的4位数据存入寄存器
    end
    else
        Endflag    <= 0;
parameter
    ready    = 6'b00_0000,
    sbit0    = 6'b00_0001,
    sbit1    = 6'b00_0010,
    sbit2    = 6'b00_0100,
    sbit3    = 6'b00_1000,
    sbit4    = 6'b01_0000;
always@(pdatabuf)
begin
    case(pdatabuf)
        4'b0001:    outhigh = 16'b0000_0000_0000_0001;
        4'b0010:    outhigh = 16'b0000_0000_0000_0010;
        4'b0011:    outhigh = 16'b0000_0000_0000_0100;
        4'b0100:    outhigh = 16'b0000_0000_0000_1000;
        4'b0101:    outhigh = 16'b0000_0000_0001_0000;
        4'b0110:    outhigh = 16'b0000_0000_0010_0000;
        4'b0111:    outhigh = 16'b0000_0000_0100_0000;
        4'b1000:    outhigh = 16'b0000_0000_1000_0000;
        4'b1001:    outhigh = 16'b0000_0001_0000_0000;
        4'b1010:    outhigh = 16'b0000_0010_0000_0000;
        4'b1011:    outhigh = 16'b0000_0100_0000_0000;
        4'b1100:    outhigh = 16'b0000_1000_0000_0000;
        4'b1101:    outhigh = 16'b0001_0000_0000_0000;
        4'b1110:    outhigh = 16'b0010_0000_0000_0000;
        4'b1111:    outhigh = 16'b0100_0000_0000_0000;
        4'b0000:    outhigh = 16'b1000_0000_0000_0000;
    endcase
end


always@(posedge scl)
    if(Startflag)
        case(mstate)
            sbit0:
            begin
                mstate  <=sbit1;
                pdata[3]<=sda;
                $display("i am in sdabit0");
            end
            sbit1:
            begin
                mstate <= sbit2;
                pdata[2]<= sda;
                $display("i am in sdabit1");
            end
            sbit2:
            begin
                mstate <= sbit3;
                pdata[1]<= sda;
                $display("i am in sdabit2");
            end
            sbit3:
            begin
                mstate <= sbit4;
                pdata[0]<= sda;
                $display("i am in sdabit3");
            end
            sbit4:
            begin
                mstate <= sbit0;
                $display("i am in sdastop");
            end
            default:
                mstate    <= sbit0;
        endcase
    else
        mstate <= sbit0;
ptosda u1(.rst(rst),.sclk(sclk),.data(data),.ack(ack),.scl(scl),.sda(sda));
endmodule
 

你可能感兴趣的:(IC,Verilog,i2c)