赞
踩
sccb不需要判断应答位
- /*qin*/
- module sccb_io
- (
- input clk,
- input rst_n,
- input sccb_write_req,
- input sccb_read_req,
- output sccb_ack,//数据发送完成
- output [7:0] sccb_read_data,
- input [6:0] lut_id,
- input [15:0] lut_addr,
- input [7:0] lut_data,
-
- inout sccb_sda,
- output reg sccb_scl
- );
- /*
- sccb_io u_sccb_io(
- .clk (clk ),
- .rst_n (rst_n ),
- .sccb_write_req (sccb_write_req ),
- .sccb_read_req (sccb_read_req ),
- .sccb_ack (sccb_ack ),
- .lut_id (lut_id ),
- .lut_addr (lut_addr ),
- .lut_data (lut_data ),
- .sccb_sda (sccb_sda ),
- .sccb_scl (sccb_scl )
- );
- */
-
- localparam cmoscnt_max = 'd2000;
- localparam cmoscnt_half = 'd1000;
- localparam comscnt_quater = 'd1500;
- localparam IDLE = 8'b00000000;
- localparam START = 8'b00000001;
- localparam ID_ADDR = 8'b00000010;
- localparam REG_ADDR = 8'b00000100;
- localparam WRITE = 8'b00001000;
- localparam READ = 8'b00010000;
- localparam STOP = 8'b00100000;
-
- wire sccb_en;
- wire scl_down;
- reg scl_frame;
- reg sdo;
- reg sdir;
- reg turnflag;
- reg [7:0] read_data;//
-
- reg [15:0] delay;//最大值必须是cmoscnt_max的两倍以上
-
- reg [7:0] ID_CNT; //发送从机地址
- reg [7:0] REG_CNT; //发送寄存器地址
- reg [7:0] DATA_CNT;//读写地址
-
- reg [15:0] sccb_cnt;
-
- reg [7:0] currentstate;
- reg [7:0] nextstate;
-
- assign sccb_en = (sccb_cnt == cmoscnt_max)?1'b1:1'b0;
- assign scl_down = (!sccb_scl && scl_frame)?1'b1:1'b0;
-
- assign sccb_sda = (sdir)?sdo:1'hz;
- assign sccb_ack = (delay == 16'd5000)?1'b1:1'b0;
- assign sccb_read_data = read_data;
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- sccb_cnt <= 'd0;
- else if(currentstate == IDLE)
- sccb_cnt <= 'd0;
- else if(currentstate == STOP)
- begin
- if(sccb_scl == 1'b1 && sdo == 1'b1)
- sccb_cnt <= sccb_cnt;
- else
- sccb_cnt <= (sccb_cnt < 2*cmoscnt_max)?sccb_cnt + 1'b1:sccb_cnt;
- end
- // else if(currentstate == START)
- // begin
- // if(turnflag)begin
- // sccb_cnt <= (sccb_cnt > cmoscnt_half)?'d0:(sccb_cnt + 1'b1);
- // turnflag <= 1'b0;
- // end
- // else
- // sccb_cnt <= sccb_cnt + 1'b1;
- // end
- else if(sccb_cnt == cmoscnt_max)
- sccb_cnt <= 'd0;
- else
- sccb_cnt <= sccb_cnt + 1'b1;
-
- end
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- scl_frame <= 1'b1;
- else
- scl_frame <= sccb_scl;
- end
-
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- sccb_scl <= 1'b1;
- else if(currentstate == IDLE)
- sccb_scl <= 1'b1;
- else if(currentstate == START)
- begin
- if(sccb_cnt == comscnt_quater)
- sccb_scl <= 1'b0;
- else
- sccb_scl <= sccb_scl;
- end
- else if(currentstate == STOP)
- begin
- if(sccb_en)
- sccb_scl <= 1'b1;
- else
- sccb_scl <= sccb_scl;
- end
- else if(sccb_en)
- sccb_scl <= ~sccb_scl;
- end
-
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- turnflag <= 1'b0;
- else if(currentstate == STOP && nextstate == START)
- turnflag <= 1'b1;
- end
-
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)begin
- ID_CNT <= 'd0;
- REG_CNT <= 'd0;
- DATA_CNT<= 'd0;
- end
- else begin
- ID_CNT <= (currentstate == ID_ADDR)?((sccb_en && sccb_scl)?(ID_CNT + 1'b1):ID_CNT):'d0;
- REG_CNT <= (currentstate == REG_ADDR)?((sccb_en && sccb_scl)?(REG_CNT + 1'b1):REG_CNT):'d0;
- DATA_CNT <= (currentstate == WRITE || currentstate == READ)?((sccb_en && sccb_scl)?(DATA_CNT + 1'b1):DATA_CNT):'d0;
- end
- end
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- sdir <= 1'b1;
- else if (sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)begin
- case(currentstate)
- IDLE: sdir <= 1'b1;
- START: sdir <= 1'b1;
- ID_ADDR: sdir <= (ID_CNT == 8'd8)?1'b0:1'b1;
- REG_ADDR: sdir <= (REG_CNT == 8'd8 || REG_CNT == 8'd17)?1'b0:1'b1;
- WRITE: sdir <= (DATA_CNT == 8'd8)?1'b0:1'b1;
- READ: sdir <= (DATA_CNT == 8'd8)?1'b1:1'b0;
- STOP: sdir <= 1'b1;//(bit_cnt == )?1'b0:1'b1;
- default: sdir <= 1'b1;
- endcase
- end
- end
-
- always @(posedge clk or negedge rst_n)
- begin
-
- end
-
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- delay <= 'd0;
- else if(currentstate == STOP)
- delay <= delay + 1'b1;
- else
- delay <= 'd0;
- end
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)
- currentstate <= IDLE;
- else
- currentstate <= nextstate;
- end
- always @(*)
- begin
- case(currentstate)
- IDLE:begin
- if(sccb_read_req || sccb_write_req)
- nextstate = START;
- else
- nextstate = IDLE;
- end
- START:begin
- if(sccb_read_req || sccb_write_req)begin
- if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_max)
- nextstate = ID_ADDR;
- else
- nextstate = START;
- end
- else
- nextstate = IDLE;
- end
- ID_ADDR:begin
- if(sccb_read_req || sccb_write_req)begin
- if(ID_CNT == 8'd9)
- nextstate = REG_ADDR;
- else
- nextstate = ID_ADDR;
- end
- else
- nextstate = IDLE;
- end
- REG_ADDR:begin
- if(sccb_read_req || sccb_write_req)begin
- if(REG_CNT == 8'd18)begin
- if(sccb_write_req)
- nextstate = WRITE;
- else
- nextstate = READ;
- end
- else
- nextstate = REG_ADDR;
- end
- else
- nextstate = IDLE;
- end
- WRITE:begin
- if(sccb_read_req || sccb_write_req)begin
- if(DATA_CNT == 8'd9)
- nextstate = STOP;
- else
- nextstate = WRITE;
- end
- else
- nextstate = IDLE;
- end
- READ:begin
- if(sccb_read_req || sccb_write_req)begin
- if(DATA_CNT == 8'd9)
- nextstate = STOP;
- else
- nextstate = READ;
- end
- else
- nextstate = IDLE;
- end
- STOP:begin
- // if(delay == 'd5000)begin
- // if(sccb_read_req || sccb_write_req)
- // nextstate = START;
- // else
- // end
- if(delay == 'd5000)
- nextstate = IDLE;
- else
- nextstate = STOP;
- end
- default:;
- endcase
- end
-
-
- always @(posedge clk or negedge rst_n)
- begin
- if(!rst_n)begin
- sdo <= 1'b1;
- read_data <= 'd0;
- end
- else begin
- case(currentstate)
- IDLE:begin
- sdo <= 1'b1;
- end
- START:begin
- if(sccb_cnt == cmoscnt_half)
- sdo <= 1'b0;
- else
- sdo <= sdo;
- end
- ID_ADDR:begin
- if(ID_CNT < 8'd7)begin
- if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
- sdo <= lut_id[8'd6 - ID_CNT];
- else
- sdo <= sdo;
- end
- else begin
- if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
- begin
- if(sccb_write_req)
- sdo <= 1'b0;
- else
- sdo <= 1'b1;
- end
- else
- sdo <= sdo;
- end
- end
- REG_ADDR:begin
- if(REG_CNT < 8'd8)begin
- if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
- sdo <= lut_addr[8'd15 - REG_CNT];//高8位
- else
- sdo <= sdo;
- end
- else if(REG_CNT < 8'd17 && REG_CNT > 8'd8)begin
- if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
- sdo <= lut_addr[8'd16 - REG_CNT];//低8位
- else
- sdo <= sdo;
- end
- else
- sdo <= 1'b1;
- end
- WRITE:begin
- if(DATA_CNT < 8'd8 )begin
- if(sccb_scl == 1'b0 && sccb_cnt == cmoscnt_half)
- sdo <= lut_data[8'd7 - DATA_CNT];
- else
- sdo <= sdo;
- end
- else
- sdo <= 1'b1;
- end
- READ:begin
- if(DATA_CNT < 8'd8 )begin
- if(sccb_scl == 1'b1 && sccb_cnt == cmoscnt_half)
- read_data[8'd7 - DATA_CNT] <= sccb_sda;
- else
- read_data <= read_data;
- end
- else begin
- read_data <= read_data;
- if(DATA_CNT == 8'd8)
- sdo <= 1'b0;
- else
- sdo <= sdo;
- end
- end
- STOP:begin
- if(sccb_scl == 1'b1 && sccb_cnt == 2*cmoscnt_max)
- sdo <= 1'b1;
- else
- sdo <= 1'b0;
- end
- default:;
- endcase
- end
- end
-
-
- endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。