TA的每日心情 | 难过 2021-8-18 12:26 |
---|
新手入门
- 积分
- 13
|
以下是代码,请各位看看哪里需要改底层i2c_bit_shif - module i2c_bit_shift(
- Clk,
- Rst_n,
-
- Cmd,
- Go,
- Rx_DATA,
- Tx_DATA,
- Trans_Done,
- ack_o,
- i2c_sclk,
- i2c_sdat
- );
- input Clk;
- input Rst_n;
-
- input [5:0]Cmd;
- input Go;
- output reg[7:0]Rx_DATA;
- input [7:0]Tx_DATA;
- output reg Trans_Done;
- output reg ack_o;
- output reg i2c_sclk;
- inout i2c_sdat;
-
- reg i2c_sdat_o;
- //系统时钟采用50MHz
- parameter SYS_CLOCK = 50_000_000;
- //SCL总线时钟采用400kHz
- parameter SCL_CLOCK = 400_000;
- //产生时钟SCL计数器最大值
- localparam SCL_CNT_M = SYS_CLOCK/SCL_CLOCK/4 - 1;
-
- reg i2c_sdat_oe;
-
- localparam
- WR = 6'b000001, // 写请求
- STA = 6'b000010, //起始位请求
- RD = 6'b000100, //读请求
- STO = 6'b001000, //停止位请求
- ACK = 6'b010000, //应答位请求
- NACK = 6'b100000; //无应答请求
-
- reg [19:0]div_cnt;
- reg en_div_cnt;
- always@(posedge Clk or negedge Rst_n)
- if(!Rst_n)
- div_cnt <= 20'd0;
- else if(en_div_cnt)begin
- if(div_cnt < SCL_CNT_M)
- div_cnt <= div_cnt + 1'b1;
- else
- div_cnt <= 0;
- end
- else
- div_cnt <= 0;
- wire sclk_plus = div_cnt == SCL_CNT_M;
-
- assign i2c_sdat = i2c_sdat_oe?(i2c_sdat_o?1'bz:1'd0):1'bz;
- //assign i2c_sdat = i2c_sdat_oe?i2c_sdat_o:1'bz;
- reg [7:0]state;
-
- localparam
- IDLE = 8'b00000001,
- GEN_STA = 8'b00000010,
- WR_DATA = 8'b00000100,
- RD_DATA = 8'b00001000,
- CHECK_ACK = 8'b00010000,
- GEN_ACK = 8'b00100000,
- GEN_STO = 8'b01000000;
-
- reg [4:0]cnt;
-
- always@(posedge Clk or negedge Rst_n)
- if(!Rst_n)begin
- Rx_DATA <= 0;
- i2c_sdat_oe <= 1'd0;
- en_div_cnt <= 1'b0;
- i2c_sdat_o <= 1'd1;
- Trans_Done <= 1'b0;
- ack_o <= 0;
- state <= IDLE;
- cnt <= 0;
- end
- else begin
- case(state)
- IDLE:
- begin
- Trans_Done <= 1'b0;
- i2c_sdat_oe <= 1'd1;
- if(Go)begin
- en_div_cnt <= 1'b1;
- if(Cmd & STA)
- state <= GEN_STA;
- else if(Cmd & WR)
- state <= WR_DATA;
- else if(Cmd & RD)
- state <= RD_DATA;
- else
- state <= IDLE;
- end
- else begin
- en_div_cnt <= 1'b0;
- state <= IDLE;
- end
- end
-
- GEN_STA:
- begin
- if(sclk_plus)begin
- if(cnt == 3)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- case(cnt)
- 0:begin i2c_sdat_o <= 1; i2c_sdat_oe <= 1'd1;end
- 1:begin i2c_sclk <= 1;end
- 2:begin i2c_sdat_o <= 0; i2c_sclk <= 1;end
- 3:begin i2c_sclk <= 0;end
- default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- endcase
- if(cnt == 3)begin
- if(Cmd & WR)
- state <= WR_DATA;
- else if(Cmd & RD)
- state <= RD_DATA;
- end
- end
- end
-
- WR_DATA:
- begin
- if(sclk_plus)begin
- if(cnt == 31)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- case(cnt)
- 0,4,8,12,16,20,24,28:begin i2c_sdat_o <= Tx_DATA[7-cnt[4:2]]; i2c_sdat_oe <= 1'd1;end //set data;
- 1,5,9,13,17,21,25,29:begin i2c_sclk <= 1;end //sclk posedge
- 2,6,10,14,18,22,26,30:begin i2c_sclk <= 1;end //sclk keep high
- 3,7,11,15,19,23,27,31:begin i2c_sclk <= 0;end //sclk negedge
- default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- endcase
- if(cnt == 31)begin
- state <= CHECK_ACK;
- end
- end
- end
-
- RD_DATA:
- begin
- if(sclk_plus)begin
- if(cnt == 31)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- case(cnt)
- 0,4,8,12,16,20,24,28:begin i2c_sdat_oe <= 1'd0; i2c_sclk <= 0;end //set data;
- 1,5,9,13,17,21,25,29:begin i2c_sclk <= 1;end //sclk posedge
- 2,6,10,14,18,22,26,30:begin i2c_sclk <= 1; Rx_DATA <= {Rx_DATA[6:0],i2c_sdat};end //sclk keep high
- 3,7,11,15,19,23,27,31:begin i2c_sclk <= 0;end //sclk negedge
- default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- endcase
- if(cnt == 31)begin
- state <= GEN_ACK;
- end
- end
- end
-
- CHECK_ACK:
- begin
- if(sclk_plus)begin
- if(cnt == 3)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- case(cnt)
- 0:begin i2c_sdat_oe <= 1'd0; i2c_sclk <= 0;end
- 1:begin i2c_sclk <= 1;end
- 2:begin ack_o <= i2c_sdat; i2c_sclk <= 1;end
- 3:begin i2c_sclk <= 0;end
- default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- endcase
- if(cnt == 3)begin
- if(Cmd & STO)
- state <= GEN_STO;
- else begin
- state <= IDLE;
- Trans_Done <= 1'b1;
- end
- end
- end
- end
-
- GEN_ACK:
- begin
- if(sclk_plus)begin
- if(cnt == 3)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- case(cnt)
- 0:begin
- i2c_sdat_oe <= 1'd1;
- i2c_sclk <= 0;
- if(Cmd & ACK)
- i2c_sdat_o <= 1'b0;
- else if(Cmd & NACK)
- i2c_sdat_o <= 1'b1;
- end
- 1:begin i2c_sclk <= 1;end
- 2:begin i2c_sclk <= 1;end
- 3:begin i2c_sclk <= 0;end
- default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- endcase
- if(cnt == 3)begin
- if(Cmd & STO)
- state <= GEN_STO;
- else begin
- state <= IDLE;
- Trans_Done <= 1'b1;
- end
- end
- end
- end
-
- GEN_STO:
- begin
- if(sclk_plus)begin
- if(cnt == 3)
- cnt <= 0;
- else
- cnt <= cnt + 1'b1;
- case(cnt)
- 0:begin i2c_sdat_o <= 0; i2c_sdat_oe <= 1'd1;end
- 1:begin i2c_sclk <= 1;end
- 2:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- 3:begin i2c_sclk <= 1;end
- default:begin i2c_sdat_o <= 1; i2c_sclk <= 1;end
- endcase
- if(cnt == 3)begin
- Trans_Done <= 1'b1;
- state <= IDLE;
- end
- end
- end
- default:state <= IDLE;
- endcase
- end
-
- endmodule
复制代码 顶层 i2c_control- <div class="blockcode"><blockquote>module i2c_control(
- Clk,
- Rst_n,
-
- wrreg_req,
- rdreg_req,
- addr,
- // addr_mode,
- wrdata,
- rddata,
- device_id,
- RW_Done,
-
- ack,
-
- i2c_sclk,
- i2c_sdat
- );
- input Clk;//时钟,50MHZ
- input Rst_n;//复位信号
-
- input wrreg_req; //写请求信号
- input rdreg_req; //读请求信号
- input [15:0]addr; //16位地址输入
- // input addr_mode; //输入地址模式,0:8位的地址,1:16位地址
- input [7:0]wrdata; //总线发送的8位数据
- output reg[7:0]rddata; //总线收到8位数据
- input [7:0]device_id; //I2C器件的ID
- output reg RW_Done; //读/写完成标志
-
- output reg ack; //从机是否应答标志
- output i2c_sclk; //i2c时钟总线
- inout i2c_sdat; //i2c数据总线
-
- reg [5:0]Cmd;
- reg [7:0]Tx_DATA;
- wire Trans_Done;
- wire ack_o;
- reg Go;
-
-
- wire [7:0]Rx_DATA;
-
- localparam
- WR = 6'b000001, // 写请求
- STA = 6'b000010, //起始位请求
- RD = 6'b000100, //读请求
- STO = 6'b001000, //停止位请求
- ACK = 6'b010000, //应答位请求
- NACK = 6'b100000; //无应答请求
-
- i2c_bit_shift i2c_bit_shift(
- .Clk(Clk),
- .Rst_n(Rst_n),
- .Cmd(Cmd),
- .Go(Go),
- .Rx_DATA(Rx_DATA),
- .Tx_DATA(Tx_DATA),
- .Trans_Done(Trans_Done),
- .ack_o(ack_o),
- .i2c_sclk(i2c_sclk),
- .i2c_sdat(i2c_sdat)
- );
-
- reg [6:0]state;
- reg [7:0]cnt;
-
- localparam
- IDLE = 7'b0000001,
- WR_REG = 7'b0000010,
- WAIT_WR_DONE = 7'b0000100,
- WR_REG_DONE = 7'b0001000,
- RD_REG = 7'b0010000,
- WAIT_RD_DONE = 7'b0100000,
- RD_REG_DONE = 7'b1000000;
-
- always@(posedge Clk or negedge Rst_n)
- if(!Rst_n)begin
- Cmd <= 6'd0;
- Tx_DATA <= 8'd0;
- Go <= 1'b0;
- rddata <= 0;
- state <= IDLE;
- ack <= 0;
- end
- else begin
- case(state)
- IDLE:
- begin
- cnt <= 0;
- ack <= 0;
- RW_Done <= 1'b0;
- if(wrreg_req)
- state <= WR_REG;
- else if(rdreg_req)
- state <= RD_REG;
- else
- state <= IDLE;
- end
-
- WR_REG:
- begin
- state <= WAIT_WR_DONE;
- case(cnt)
- 0:write_byte(WR | STA, device_id);
- 1:write_byte(WR, addr[15:8]);
- 2:write_byte(WR, addr[7:0]);
- 3:write_byte(WR | STO, wrdata);
- default:;
- endcase
- end
-
- WAIT_WR_DONE:
- begin
- Go <= 1'b0;
- if(Trans_Done)begin
- ack <= ack | ack_o;
- case(cnt)
- 0: begin cnt <= 1; state <= WR_REG;end
- 1:
- begin
- state <= WR_REG;
- //if(addr_mode)
- cnt <= 2;
- //else
- //cnt <= 3;
- end
-
- 2: begin
- cnt <= 3;
- state <= WR_REG;
- end
- 3:state <= WR_REG_DONE;
- default:state <= IDLE;
- endcase
- end
- end
-
- WR_REG_DONE:
- begin
- RW_Done <= 1'b1;
- state <= IDLE;
- end
-
- RD_REG:
- begin
- state <= WAIT_RD_DONE;
- case(cnt)
- 0:write_byte(WR | STA, device_id);
- 1:/*if(addr_mode)
- write_byte(WR, addr[15:8]);
- else*/
- write_byte(WR, addr[15:8]);
- 2:write_byte(WR, addr[7:0]);
- 3:write_byte(WR | STA, device_id | 8'd1);
- 4:read_byte(RD | NACK | STO);
- default:;
- endcase
- end
-
- WAIT_RD_DONE:
- begin
- Go <= 1'b0;
- if(Trans_Done)begin
- if(cnt <= 3)
- ack <= ack | ack_o;
- case(cnt)
- 0: begin cnt <= 1; state <= RD_REG;end
- 1:
- begin
- state <= RD_REG;
- //if(addr_mode)
- cnt <= 2;
- //else
- // cnt <= 3;
- end
-
- 2: begin
- cnt <= 3;
- state <= RD_REG;
- end
- 3:begin
- cnt <= 4;
- state <= RD_REG;
- end
- 4:state <= RD_REG_DONE;
- default:state <= IDLE;
- endcase
- end
- end
-
- RD_REG_DONE:
- begin
- RW_Done <= 1'b1;
- rddata <= Rx_DATA;
- state <= IDLE;
- end
- default:state <= IDLE;
- endcase
- end
-
- task read_byte;
- input [5:0]Ctrl_Cmd;
- begin
- Cmd <= Ctrl_Cmd;
- Go <= 1'b1;
- end
- endtask
-
- task write_byte;
- input [5:0]Ctrl_Cmd;
- input [7:0]Wr_Byte_Data;
- begin
- Cmd <=Ctrl_Cmd;
- Go <= 1'b1;
- end
- endtask
-
- task write_byte;
- input [5:0]Ctrl_Cmd;
- input [7:0]Wr_Byte_Data;
- begin
- Cmd <= Ctrl_Cmd;
- Tx_DATA <= Wr_Byte_Data;
- Go <= 1'b1;
- end
- endtask
- endmodule
复制代码 testbench i2c_control_tb
- `timescale 1ns/1ns
- module i2c_control_tb;
- reg Clk;
- reg Rst_n;
-
- reg wrreg_req;
- reg rdreg_req;
- reg [15:0]addr;
- // reg addr_mode;
- reg [7:0]wrdata;
- wire [7:0]rddata;
- reg [7:0]device_id;
- wire RW_Done;
-
- wire ack;
- wire i2c_sclk;
- wire i2c_sdat;
-
- pullup PUP (i2c_sdat);
- i2c_control i2c_control(
- .Clk(Clk),
- .Rst_n(Rst_n),
- .wrreg_req(wrreg_req),
- .rdreg_req(rdreg_req),
- .addr(addr),
- // .addr_mode(addr_mode),
- .wrdata(wrdata),
- .rddata(rddata),
- .device_id(device_id),
- .RW_Done(RW_Done),
- .ack(ack),
- .i2c_sclk(i2c_sclk),
- .i2c_sdat(i2c_sdat)
- );
- M24LC128 M24LC128(
- //M24LC64 M24LC64(
- //.A0(0),
- //.A1(0),
- //.A2(0),
- //.WP(0),
- .SDA(i2c_sdat),
- .SCL(i2c_sclk),
- .RESET(~Rst_n)
- );
-
- initial Clk = 1;
- always #10 Clk = ~Clk;
-
- initial begin
- Rst_n = 0;
- rdreg_req = 0;
- wrreg_req = 0;
- #2001;
- Rst_n = 1;
- #2000;
-
- write_one_byte(8'hA0,8'h0A,8'hd1);
- //#20000;
- write_one_byte(8'hA0,8'h0B,8'hd2);
- //#20000;
- write_one_byte(8'hA0,8'h0C,8'hd3);
- //#20000;
- write_one_byte(8'hA0,8'h0D,8'hd4);
- //#20000;
- write_one_byte(8'hA0,8'h0F,8'hd5);
- //#20000;
-
- read_one_byte(8'hA0,8'h0A);
- //#20000;
- read_one_byte(8'hA0,8'h0B);
- //#20000;
- read_one_byte(8'hA0,8'h0C);
- //#20000;
- read_one_byte(8'hA0,8'h0D);
- //#20000;
- read_one_byte(8'hA0,8'h0F);
- //#20000;
- $stop;
- end
-
- task write_one_byte;
- input [7:0]id;
- input [7:0]mem_address;
- input [7:0]data;
- begin
- addr = {8'd0,mem_address};
- device_id = id;
- // addr_mode = 1;
- wrdata = data;
- wrreg_req = 1;
- #20;
- wrreg_req = 0;
- @(posedge RW_Done);
- #20000;
- end
- endtask
-
- task read_one_byte;
- input [7:0]id;
- input [7:0]mem_address;
- begin
- addr = {8'd0,mem_address};
- device_id = id;
- // addr_mode = 1;
- rdreg_req = 1;
- #20;
- rdreg_req = 0;
- @(posedge RW_Done);
- #20000;
- end
- endtask
- endmodule
复制代码
|
-
|