下面为写部分代码
module bmp280_wr(
input wire sclk,//system clock 100MHz
input wire rst,//system reset,active high
input wire start,//starting signal for sending datas
input wire[7:0] regaddr,//register address
input wire[7:0] data,//data to be send
output reg send_ok,
output reg send_fail,
output reg wr_scl,//400kHz clock for slave device
output wire wr_sdo,//define slave device address bit[0]=111011_bit[0]
inout wire wr_sda //iic data port for input and output
);
parameter SCLKCNT_MAX=250-1;//100_000_000/400_000=250 for 400kHz scl
parameter IDLE =4'b0001;
parameter START=4'b0010;
parameter SEND =4'b0100;
parameter STOP =4'b1000;
reg [3:0] state;
reg [7:0] sclk_cnt;
reg [6:0] slave_addr;
reg sda_r;
reg oe;
reg [3:0] bit_cnt;
reg [3:0] byte_cnt;
reg [23:0] data_temp;
always @(posedge sclk) begin
if (rst==1'b1) begin
data_temp<='d0;
end
else if (start==1'b1) begin
data_temp<={slave_addr,1'b0,regaddr,data};
end
else if(state==SEND && bit_cnt!='d8 && sclk_cnt=='d0)begin
data_temp<=data_temp<<1;
end
end
always @(*) begin
oe=(bit_cnt=='d8)?1'b0:1'b1;
end
assign wr_sda = (oe==1'b1)?sda_r:1'bz;
assign wr_sdo = 1'b0;//slave device address 1110_110
always @(posedge sclk) begin
if (rst==1'b1) begin
slave_addr<='d0;
end
else if (wr_sdo==1'b1) begin
slave_addr<=7'b1110_111;
end
else begin
slave_addr<=7'b1110_110;
end
end
//sclk_cnt
always @(posedge sclk) begin
if (rst==1'b1) begin
sclk_cnt<='d0;
end
else if ((state==IDLE) || (sclk_cnt==SCLKCNT_MAX)) begin
sclk_cnt<='d0;
end
else begin
sclk_cnt<=sclk_cnt+1'b1;
end
end
//bit_cnt
always @(posedge sclk) begin
if (rst==1'b1) begin
bit_cnt<='d0;
end
if(state!=SEND)begin
bit_cnt<='d0;
end
else if (state==SEND && sclk_cnt==SCLKCNT_MAX) begin
if(bit_cnt=='d8)begin
bit_cnt<='d0;
end
else begin
bit_cnt<=bit_cnt+1'b1;
end
end
end
//byte_cnt
always @(posedge sclk) begin
if (rst==1'b1) begin
byte_cnt<='d0;
end
else if (state==SEND) begin
if(byte_cnt=='d2 && bit_cnt=='d8 && sclk_cnt==SCLKCNT_MAX)
byte_cnt<='d0;
else if(byte_cnt!='d2 && bit_cnt=='d8 && sclk_cnt==SCLKCNT_MAX)begin
byte_cnt<=byte_cnt+1'b1;
end
end
else begin
byte_cnt<='d0;
end
end
//state
always @(posedge sclk) begin
if (rst==1'b1) begin
state<=IDLE;
end
else begin
case(state)
IDLE:begin
if(start==1'b1)begin
state<=START;
end
end
START:begin
if(sclk_cnt==SCLKCNT_MAX)begin
state<=SEND;
end
end
SEND:begin
if(bit_cnt=='d8 && sclk_cnt==(SCLKCNT_MAX>>1) && wr_sda==1'b1)begin
state<=IDLE;
end
else if(byte_cnt=='d2 && bit_cnt=='d8 && sclk_cnt==SCLKCNT_MAX)begin
state<=STOP;
end
end
STOP:begin
if(sclk_cnt==SCLKCNT_MAX)begin
state<=IDLE;
end
end
default:state<=IDLE;
endcase
end
end
//sda_r
always @(posedge sclk) begin
if (rst==1'b1) begin
sda_r<=1'b1;
end
else begin
case(state)
START:begin
if(sclk_cnt>(SCLKCNT_MAX>>1))begin
sda_r<=1'b0;
end
else begin
sda_r<=1'b1;
end
end
SEND:begin
if(bit_cnt!='d8 && sclk_cnt=='d0)begin
sda_r<=data_temp[23];
end
end
STOP:begin
if(sclk_cnt>((SCLKCNT_MAX>>1)+(SCLKCNT_MAX>>2)))begin
sda_r<=1'b1;
end
else begin
sda_r<=1'b0;
end
end
default:sda_r<=1'b1;
endcase
end
end
//wr_scl
always @(posedge sclk) begin
if (rst==1'b1) begin
wr_scl<=1'b1;
end
else begin
case(state)
START:begin
if(sclk_cnt==SCLKCNT_MAX)begin
wr_scl<=1'b0;
end
else begin
wr_scl<=1'b1;
end
end
SEND:begin
if(sclk_cnt==SCLKCNT_MAX)begin
wr_scl<=1'b0;
end
else if(sclk_cnt==(SCLKCNT_MAX>>1))begin
wr_scl<=1'b1;
end
end
STOP:begin
if(sclk_cnt=='d0)begin
wr_scl<=1'b0;
end
else if(sclk_cnt==(SCLKCNT_MAX>>1))begin
wr_scl<=1'b1;
end
end
default:wr_scl<=1'b1;
endcase
end
end
//send_fail
always @(posedge sclk) begin
if (rst==1'b1) begin
send_fail<=1'b0;
end
else if (state==SEND && bit_cnt=='d8 && sclk_cnt==(SCLKCNT_MAX>>1) && wr_sda==1'b1) begin
send_fail<=1'b1;
end
else begin
send_fail<=1'b0;
end
end
//send_ok
always @(posedge sclk) begin
if (rst==1'b1) begin
send_ok<=1'b0;
end
else if (state==STOP && sclk_cnt==SCLKCNT_MAX) begin
send_ok<=1'b1;
end
else begin
send_ok<=1'b0;
end
end
endmodule
接着就是写代码仿真文件:
`timescale 1ns/1ns
module tb_bmp280_wr (); /* this is automatically generated */
//
reg clk;
reg rst;
reg start;
reg [7:0] regaddr;
reg [7:0] data;
wire send_ok;
wire send_fail;
wire wr_scl;
wire wr_sdo;
wand wr_sda;
reg wr_sda_r;
initial begin
clk = 0;
forever #(5) clk = ~clk;
end
// synchronous reset
initial begin
rst = 1;
start=0;
regaddr=0;
data=0;
repeat(100)@(posedge clk)
rst = 0;
repeat(100)@(posedge clk);
send(8'hf5,8'h55);
send(8'hf4,8'haa);
$stop;
end
bmp280_wr inst_bmp280_wr (
.sclk (clk),
.rst (rst),
.start (start),
.regaddr (regaddr),
.data (data),
.send_ok (send_ok),
.send_fail (send_fail),
.wr_scl (wr_scl),
.wr_sdo (wr_sdo),
.wr_sda (wr_sda)
);
task send;
input [7:0] regaddr_r;
input [7:0] data_r;
begin
start=0;
regaddr=regaddr_r;
data=data_r;
@(negedge clk) start=1;
@(negedge clk) start=0;
@(posedge send_ok or posedge send_fail);
#1000;
end
endtask
always @(posedge clk) begin
if (rst==1'b1) begin
wr_sda_r<=1'b1;
end
else if ( inst_bmp280_wr.bit_cnt==8) begin
wr_sda_r<=1'b0;
end
else begin
wr_sda_r<=1'b1;
end
end
assign wr_sda = wr_sda_r;
endmodule
仿真波形: