赞
踩
module iic_drive#( parameter P_ADDR_WIDTH = 16 )( input i_clk ,//模块输入时钟 input i_rst ,//模块输入复位-高有效 /*--------用户接口--------*/ input [6 :0] i_drive ,//用户输入设备地址 input [15:0] i_operation_addr ,//用户输入存储地址 input [7 :0] i_operation_len ,//用户输入读写长度 input [1 :0] i_operation_type ,//用户输入操作类型 input i_opeartion_valid ,//用户输入有效信号 output o_operation_ready ,//用户输出准备信号 input [7 :0] i_write_data ,//用户输入写数据 output o_write_req ,//用户写数据请求信号 output [7 :0] o_read_data ,//输出IIC读到的数据 output o_read_valid ,//输出IIC读数据有效 /*--------IIC接口--------*/ output o_iic_scl ,//IIC的时钟 inout io_iic_sda //IIC的双向数据项 ); /***************function**************/ /***************parameter*************/ parameter P_ST_IDLE = 0 ,//状态机-空闲 P_ST_START = 1 ,//状态机-起始 P_ST_UADDR = 2 ,//状态机-设备地址 P_ST_DADDR1 = 3 ,//状态机-存储地址高位 P_ST_DADDR2 = 4 ,//状态机-存储地址地位 P_ST_WRITE = 5 ,//状态机-写数据 P_ST_RESTART= 6 , P_ST_READ = 7 ,//状态机-读数据 P_ST_WAIT = 8 , P_ST_STOP = 9 ,//状态机-停止 P_ST_EMPTY = 10 ; localparam P_W = 1 ,//2'b01 P_R = 2 ;//2'b10 /***************port******************/ /***************mechine***************/ reg [7 :0] r_st_current ;//当前状态机 reg [7 :0] r_st_next ;//下一个状态机 reg [7 :0] r_st_cnt ;//状态机计数器 /***************reg*******************/ reg ro_operation_ready ;//操作准备信号 reg ro_write_req ;//写数据请求 reg ro_write_valid ;//写数据有效 reg [7 :0] ro_read_data ;//读数据 reg ro_read_valid ;//读数据有效 reg ro_iic_scl ;//IIC的SCL输出寄存器 reg [7 :0] ri_drive ;//输入的设备地址 reg [15:0] ri_operation_addr ;//输入的存储地址 reg [7 :0] ri_operation_len ;//输入的读写长度 reg [1 :0] ri_operation_type ;//输入读写类型 reg [7 :0] ri_write_data ;//输入的写数据 reg r_iic_st ;//iic时钟状态 reg r_iic_sda_ctrl ;//iic数据三态门控制信号 reg ro_iic_sda ;//iic数据信号 reg [7 :0] r_wr_cnt ;//读写数据bit计数器 reg r_slave_ack ;//iic操作里的从机应答 reg r_ack_valid ;//应答有效 reg r_st_restart ; reg r_ack_lock ; reg [7 :0] r_read_drive ; /***************wire******************/ wire w_operation_active ;//操作激活信号 wire w_st_trun ;//状态机跳转信号 wire w_iic_sda ;//iic数据线输入信号 /***************component*************/ /***************assign****************/ assign o_operation_ready = ro_operation_ready ;//准备信号 assign o_write_req = ro_write_req ;//写数据请求信号 assign o_read_data = ro_read_data ;//读数据 assign o_read_valid = ro_read_valid ;//读数据有效 assign o_iic_scl = ro_iic_scl ;//iic的scl assign w_operation_active = i_opeartion_valid & o_operation_ready ;//激活信号 assign w_st_trun = r_st_cnt == 8 && r_iic_st ;//状态机跳转条件 //三态门使用 assign io_iic_sda = r_iic_sda_ctrl ? ro_iic_sda : 1'bz ;//三态门输出 assign w_iic_sda = !r_iic_sda_ctrl ? io_iic_sda : 1'b0 ;//三态门输入 // IOBUF #( // .DRIVE (12 ), // .IBUF_LOW_PWR ("TRUE" ), // .IOSTANDARD ("DEFAULT" ), // .SLEW ("SLOW" ) // ) // IOBUF_u0 // ( // .O (ro_iic_sda ), // .IO (io_iic_sda ), // .I (w_iic_sda ), // .T (!r_iic_sda_ctrl ) // ); /***************always****************/ //第一段状态 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_st_current <= P_ST_IDLE; else r_st_current <= r_st_next; end //状态机跳转 always@(*) begin case(r_st_current) P_ST_IDLE : r_st_next <= w_operation_active ? P_ST_START : P_ST_IDLE ;//空闲,操作激活时跳转到起始状态 P_ST_START : r_st_next <= P_ST_UADDR; //起始状态,跳转设备地址 P_ST_UADDR : r_st_next <= w_st_trun ? r_st_restart ? P_ST_READ : P_ST_DADDR1 //判断是否时重启,重启转入读状态,不是重启转入写存储地址状态 : P_ST_UADDR ; //写设备地址,写完跳转存储地址 P_ST_DADDR1 : r_st_next <= r_slave_ack ? P_ST_STOP : //存储地址,先等待应答,应答后操作结束跳转存储地址低位 w_st_trun ? P_ST_DADDR2 : P_ST_DADDR1 ; P_ST_DADDR2 : r_st_next <= w_st_trun & ri_operation_type == P_W ? P_ST_WRITE ://存储地址低位,判断读写,读跳转读状态,写跳转写状态 w_st_trun & ri_operation_type == P_R ? P_ST_RESTART : P_ST_DADDR2 ; P_ST_WRITE : r_st_next <= w_st_trun & r_wr_cnt == ri_operation_len - 1 ? P_ST_WAIT : P_ST_WRITE ;//写数据状态,写完目标长度跳转结束 P_ST_RESTART: r_st_next <= P_ST_STOP; //读数据时,重启总线状态 P_ST_READ : r_st_next <= w_st_trun ? P_ST_WAIT : P_ST_READ ;//读数据状态,写完目标长度跳转结束 P_ST_WAIT : r_st_next <= P_ST_STOP ; P_ST_STOP : r_st_next <= r_st_cnt == 1? P_ST_EMPTY : P_ST_STOP; P_ST_EMPTY : r_st_next <= r_st_restart | r_ack_lock ? P_ST_START : P_ST_IDLE; //空状态,等待IIC成功停止,判断是否重启,重启转入START,不重启转入IDLE default : r_st_next <= P_ST_IDLE; endcase end //iic应答状态,1为没应答 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_ack_lock <= 'd0; else if(r_ack_valid && !w_iic_sda && r_st_current == P_ST_DADDR1) r_ack_lock <= 'd0; else if(r_ack_valid && w_iic_sda && r_st_current == P_ST_DADDR1) r_ack_lock <= 'd1; else r_ack_lock <= r_ack_lock; end //读数据时,假写操作后重启信号 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_st_restart <= 'd0; else if(r_st_current == P_ST_READ) r_st_restart <= 'd0; else if(r_st_current == P_ST_RESTART) r_st_restart <= 'd1; else r_st_restart <= r_st_restart; end //操作准备信号 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_operation_ready <= 'd1; else if(w_operation_active) ro_operation_ready <= 'd0; else if(r_st_current == P_ST_IDLE) ro_operation_ready <= 'd1; else ro_operation_ready <= ro_operation_ready; end //寄存操作数据 always@(posedge i_clk,posedge i_rst) begin if(i_rst) begin ri_drive <= 'd0; ri_operation_addr <= 'd0; ri_operation_len <= 'd0; ri_operation_type <= 'd0; end else if(w_operation_active) begin ri_drive <= {i_drive,1'b0}; ri_operation_addr <= i_operation_addr ; ri_operation_len <= i_operation_len ; ri_operation_type <= i_operation_type ; end else begin ri_drive <= ri_drive ; ri_operation_addr <= ri_operation_addr ; ri_operation_len <= ri_operation_len ; ri_operation_type <= ri_operation_type ; end end always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_read_drive <= 'd0; else if(w_operation_active) r_read_drive <= {i_drive,1'b1}; else r_read_drive <= r_read_drive; end //状态计数器 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_st_cnt <= 'd0; else if(r_st_current != r_st_next || ro_write_valid || ro_read_valid)//状态跳转、写完8bit数、读写8bit数 r_st_cnt <= 'd0; else if(r_st_current == P_ST_STOP) r_st_cnt <= r_st_cnt + 1; else if(r_iic_st) r_st_cnt <= r_st_cnt + 1; else r_st_cnt <= r_st_cnt; end //iic时钟 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_iic_scl <= 'd1; else if(r_st_current >= P_ST_UADDR && r_st_current <= P_ST_WAIT) ro_iic_scl <= ~ro_iic_scl; else ro_iic_scl <= 'd1; end //iic时钟状态 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_iic_st <= 'd0; else if(r_st_current >= P_ST_UADDR && r_st_current <= P_ST_WAIT) r_iic_st <= ~r_iic_st; else r_iic_st <= 'd0; end //iic数据线三态门控制 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_iic_sda_ctrl <= 'd0; else if(r_st_cnt == 8 || r_st_next == P_ST_IDLE) r_iic_sda_ctrl <= 'd0; else if(r_st_current >= P_ST_START && r_st_current <= P_ST_WRITE || r_st_current == P_ST_STOP) r_iic_sda_ctrl <= 'd1; else r_iic_sda_ctrl <= r_iic_sda_ctrl; end //iic数据线写数据 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_iic_sda <= 'd0; else if(r_st_current == P_ST_START) ro_iic_sda <= 'd0; else if(r_st_current == P_ST_UADDR) ro_iic_sda <= r_st_restart ? r_read_drive[7 - r_st_cnt] : ri_drive[7 - r_st_cnt]; else if(r_st_current == P_ST_DADDR1) ro_iic_sda <= ri_operation_addr[15 - r_st_cnt]; else if(r_st_current == P_ST_DADDR2) ro_iic_sda <= ri_operation_addr[7 - r_st_cnt]; else if(r_st_current == P_ST_WRITE) ro_iic_sda <= ri_write_data[7 - r_st_cnt]; else if(r_st_current == P_ST_STOP && r_st_cnt == 1) ro_iic_sda <= 'd1; else ro_iic_sda <= 'd0; end //写请求 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_write_req <= 'd0; else if(r_st_current == P_ST_DADDR2 && ri_operation_type == P_W && r_st_cnt == 7 && r_iic_st) ro_write_req <= 'd1; else if(r_st_current >= P_ST_DADDR2 && ri_operation_type == P_W && r_st_cnt == 7 && r_iic_st) ro_write_req <= r_wr_cnt < ri_operation_len - 1 ? 1'b1 : 1'b0; else ro_write_req <= 'd0; end //写有效 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_write_valid <= 'd0; else ro_write_valid <= ro_write_req; end //写数据 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ri_write_data <= 'd0; else if(ro_write_valid) ri_write_data <= i_write_data; else ri_write_data <= ri_write_data; end //读写计数器 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_wr_cnt <= 'd0; else if(r_st_current == P_ST_IDLE) r_wr_cnt <= 'd0; else if((r_st_current == P_ST_WRITE || r_st_current == P_ST_READ) && w_st_trun) r_wr_cnt <= r_wr_cnt + 1; else r_wr_cnt <= r_wr_cnt; end //读出数据 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_read_data <= 'd0; else if(r_st_current == P_ST_READ && r_st_cnt >= 1 && r_st_cnt <= 8 && !r_iic_st) ro_read_data <= {ro_read_data[6:0],w_iic_sda}; else ro_read_data <= ro_read_data; end //读出数据有效 always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_read_valid <= 'd0; else if(r_st_current == P_ST_READ && r_st_cnt == 8 && !r_iic_st) ro_read_valid <= 'd1; else ro_read_valid <= 'd0; end //从机应答信号 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_slave_ack <= 'd0; else if(r_ack_valid) r_slave_ack <= w_iic_sda; else r_slave_ack <= 'd0; end //指示应答有效信号 always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_ack_valid <= 'd0; else r_ack_valid <= w_st_trun; end endmodule
module my_ctrl( input i_clk , input i_rst , input [2 :0] i_ctrl_eeprom_addr , input [15:0] i_ctrl_operation_addr , input [1 :0] i_ctrl_operation_type , input [7 :0] i_ctrl_operation_len , input i_ctrl_opeartion_valid , output o_ctrl_operation_ready , input [7 :0] i_ctrl_write_data , input i_ctrl_write_sop , input i_ctrl_write_eop , input i_ctrl_write_valid , output [7 :0] o_ctrl_read_data , output o_ctrl_read_valid , /*--------iic dirve--------*/ output [6 :0] o_drive ,//用户输入设备地址 output [15:0] o_operation_addr ,//用户输入存储地址 output [7 :0] o_operation_len ,//用户输入读写长度 output [1 :0] o_operation_type ,//用户输入操作类型 output o_opeartion_valid ,//用户输入有效信号 input i_operation_ready ,//用户输出准备信号 output [7 :0] o_write_data ,//用户输入写数据 input i_write_req ,//用户写数据请求信号 input [7 :0] i_read_data ,//输出IIC读到的数据 input i_read_valid //输出IIC读数据有效 ); /***************function**************/ /***************parameter*************/ localparam P_ST_IDLE = 0 , P_ST_WRITE = 1 , P_ST_WAIT = 2 , P_ST_READ = 3 , P_ST_REREAD = 4 , P_ST_OREAD = 5 ; /***************port******************/ /***************mechine***************/ reg [7 :0] r_st_current ; reg [7 :0] r_st_next ; /***************reg*******************/ reg ro_ctrl_operation_ready ; reg [7 :0] ro_ctrl_read_data ; reg ro_ctrl_read_valid ; reg [7 :0] ri_ctrl_write_data ; reg ri_ctrl_write_sop ; reg ri_ctrl_write_eop ; reg ri_ctrl_write_valid ; reg [2 :0] ri_ctrl_eeprom_addr ; reg [15:0] ri_ctrl_operation_addr ; reg [1 :0] ri_ctrl_operation_type ; reg [7 :0] ri_ctrl_operation_len ; reg ri_operation_ready ; reg [7 :0] ri_read_data ; reg ri_read_valid ; reg [6 :0] ro_drive ; reg [15:0] ro_operation_addr ; reg [7 :0] ro_operation_len ; reg [1 :0] ro_operation_type ; reg ro_opeartion_valid ; reg r_fifo_read_en ; reg [7 :0] r_read_cnt ; reg [15:0] r_read_addr ; reg r_read_vld_1d ; /***************wire******************/ wire w_ctrl_active ; wire w_drive_end ; wire w_drive_act ; wire [7 :0] w_fifo_read_data ; wire w_fifo_empty ; /***************component*************/ FIFO_8X1024 FIFO_8X1024_WRITE_U0 ( .clk (i_clk ), .srst (i_rst ), .din (ri_ctrl_write_data ), .wr_en (ri_ctrl_write_valid ), .rd_en (i_write_req ), .dout (o_write_data ), .full (), .empty () ); FIFO_8X1024 FIFO_8X1024_READ_U0 ( .clk (i_clk ), .srst (i_rst ), .din (ri_read_data ), .wr_en (ri_read_valid ), .rd_en (r_fifo_read_en ), .dout (w_fifo_read_data ), .full (), .empty (w_fifo_empty ) ); /***************assign****************/ assign o_ctrl_operation_ready = ro_ctrl_operation_ready ; assign o_ctrl_read_data = ro_ctrl_read_data ; assign o_ctrl_read_valid = r_read_vld_1d ; assign w_ctrl_active = i_ctrl_opeartion_valid&o_ctrl_operation_ready; assign w_drive_end = i_operation_ready & !ri_operation_ready; assign w_drive_act = o_opeartion_valid & i_operation_ready; assign o_drive = ro_drive ; assign o_operation_addr = ro_operation_addr ; assign o_operation_len = ro_operation_len ; assign o_operation_type = ro_operation_type ; assign o_opeartion_valid = ro_opeartion_valid; /***************always****************/ always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_st_current <= P_ST_IDLE; else r_st_current <= r_st_next; end always@(*) begin case(r_st_current) P_ST_IDLE :r_st_next = w_ctrl_active && i_ctrl_operation_type == 1 ? P_ST_WRITE : w_ctrl_active && i_ctrl_operation_type == 2 ? P_ST_WAIT : P_ST_IDLE; P_ST_WRITE :r_st_next = w_drive_end ? P_ST_IDLE : P_ST_WRITE; P_ST_WAIT :r_st_next = P_ST_READ; P_ST_READ :r_st_next = w_drive_end ? r_read_cnt == ri_ctrl_operation_len - 1 ? P_ST_OREAD : P_ST_REREAD : P_ST_READ; P_ST_REREAD :r_st_next = P_ST_READ; P_ST_OREAD :r_st_next = w_fifo_empty ? P_ST_IDLE : P_ST_OREAD; default :r_st_next = P_ST_IDLE; endcase end always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_fifo_read_en <= 'd0; else if(w_fifo_empty) r_fifo_read_en <= 'd0; else if(r_st_current != P_ST_OREAD && r_st_next == P_ST_OREAD) r_fifo_read_en <= 'd1; else r_fifo_read_en <= r_fifo_read_en; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_ctrl_read_data <= 'd0; else ro_ctrl_read_data <= w_fifo_read_data; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_ctrl_read_valid <= 'd0; else if(w_fifo_empty) ro_ctrl_read_valid <= 'd0; else if(r_fifo_read_en) ro_ctrl_read_valid <= 'd1; else ro_ctrl_read_valid <= ro_ctrl_read_valid; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_read_vld_1d <= 'd0; else r_read_vld_1d <= ro_ctrl_read_valid; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) begin ri_ctrl_eeprom_addr <= 'd0; ri_ctrl_operation_addr <= 'd0; ri_ctrl_operation_type <= 'd0; ri_ctrl_operation_len <= 'd0; end else if(w_ctrl_active) begin ri_ctrl_eeprom_addr <= i_ctrl_eeprom_addr ; ri_ctrl_operation_addr <= i_ctrl_operation_addr; ri_ctrl_operation_type <= i_ctrl_operation_type; ri_ctrl_operation_len <= i_ctrl_operation_len; end else begin ri_ctrl_eeprom_addr <= ri_ctrl_eeprom_addr ; ri_ctrl_operation_addr <= ri_ctrl_operation_addr; ri_ctrl_operation_type <= ri_ctrl_operation_type; ri_ctrl_operation_len <= ri_ctrl_operation_len; end end always@(posedge i_clk,posedge i_rst) begin if(i_rst) begin ri_ctrl_write_data <= 'd0; ri_ctrl_write_sop <= 'd0; ri_ctrl_write_eop <= 'd0; ri_ctrl_write_valid <= 'd0; end else begin ri_ctrl_write_data <= i_ctrl_write_data ; ri_ctrl_write_sop <= i_ctrl_write_sop ; ri_ctrl_write_eop <= i_ctrl_write_eop ; ri_ctrl_write_valid <= i_ctrl_write_valid ; end end always@(posedge i_clk,posedge i_rst) begin if(i_rst) ro_ctrl_operation_ready <= 'd1; else if(w_ctrl_active) ro_ctrl_operation_ready <= 'd0; else if(r_st_current == P_ST_IDLE) ro_ctrl_operation_ready <= 'd1; else ro_ctrl_operation_ready <= ro_ctrl_operation_ready; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) ri_operation_ready <= 'd0; else ri_operation_ready <= i_operation_ready; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) begin ri_read_data <= 'd0; ri_read_valid <= 'd0; end else begin ri_read_data <= i_read_data ; ri_read_valid <= i_read_valid; end end always@(posedge i_clk,posedge i_rst) begin if(i_rst) begin ro_drive <= 'd0; ro_operation_addr <= 'd0; ro_operation_len <= 'd0; ro_operation_type <= 'd0; ro_opeartion_valid <= 'd0; end else if(w_drive_act) begin ro_drive <= 'd0; ro_operation_addr <= 'd0; ro_operation_len <= 'd0; ro_operation_type <= 'd0; ro_opeartion_valid <= 'd0; end else if(ri_ctrl_write_eop) begin ro_drive <= {4'b1010,ri_ctrl_eeprom_addr}; ro_operation_addr <= ri_ctrl_operation_addr; ro_operation_len <= ri_ctrl_operation_len; ro_operation_type <= ri_ctrl_operation_type; ro_opeartion_valid <= 'd1; end else if(r_st_next == P_ST_READ && r_st_current != P_ST_READ) begin ro_drive <= {4'b1010,ri_ctrl_eeprom_addr}; ro_operation_addr <= r_read_addr; ro_operation_len <= 1; ro_operation_type <= ri_ctrl_operation_type; ro_opeartion_valid <= 'd1; end else begin ro_drive <= ro_drive ; ro_operation_addr <= ro_operation_addr ; ro_operation_len <= ro_operation_len ; ro_operation_type <= ro_operation_type ; ro_opeartion_valid <= ro_opeartion_valid; end end always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_read_addr <= 'd0; else if(w_ctrl_active) r_read_addr <= i_ctrl_operation_addr; else if(r_st_current == P_ST_READ && w_drive_end) r_read_addr <= r_read_addr + 1 ; else r_read_addr <= r_read_addr; end always@(posedge i_clk,posedge i_rst) begin if(i_rst) r_read_cnt <= 'd0; else if(r_st_current == P_ST_IDLE) r_read_cnt <= 'd0; else if(r_st_current == P_ST_READ && w_drive_end) r_read_cnt <= r_read_cnt +1; else r_read_cnt <= r_read_cnt; end endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。