⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart2iic.v

📁 UART转I2C的Verilog HDL代码
💻 V
字号:
module uart2iic_new(reset, clk24m, uart_in, uart_out, scl, sda,
uart_loop, ack_req, dat_req, data_okb);
input reset, clk24m, uart_in, uart_loop ;  //clk24m is 24mHz 
//00:add_buff, 01:data_buf, 11:comd_flag  
inout sda ;
output scl, ack_req, uart_out, data_okb ; //Bauld rate is 115200=24000000/208
output [3:0] dat_req ;
reg [7:0] add_buf, data_buf, recv_data ;
//reg rbf, tbf, erbf, etbe;  // rbf = 'b1 indicates a byte received from IIC bus, tbf = 'b1 indicates a efficient byte hasn't been sent yet
reg comd_flag, sda_buf; 
// comd_flag = 'b1 indicates an operation is pending, erbf and etbe are INT enable signals
//reg [1:0] wr_reg, rd_reg;
reg [1:0] urx_st, new_rst, low_cunt, cyc_num ;
reg [2:0] iic_state, new_state, dev_add ;
reg [3:0] bit_cunt, samp_cunt, ml_count, symb_cunt ;
reg [3:0] utx_st, new_tst ; 
reg [5:0] iic_div ;
reg [7:1] urx_data ;
reg [7:0] clk_div,tx_samp_cunt ;
wire [7:0] comm_data ;
wire rx_dt_sft_en, u2ii_enb, trst_ok, samp_ok, 
ml_symb, phas_end, symb_end, data_rdy, sda_data, iic_op_enb;

//for uart_receive
parameter  rs0 = 2'b00 ;//receive idle
parameter  rs1 = 2'b01 ;//start test
parameter  rs2 = 2'b11 ;//frame end test
parameter  rs3 = 2'b10 ;//symbol finished

parameter  ts0 = 4'b0000 ;//transmit idle
parameter  ts1 = 4'b0001 ;//transmit start
parameter  ts2 = 4'b0011 ;//transmit lsb
parameter  ts3 = 4'b0010 ;//transmit bit[1]
parameter  ts4 = 4'b0110 ;//transmit bit[2]
parameter  ts5 = 4'b0111 ;//transmit bit[3]
parameter  ts6 = 4'b0101 ;//transmit bit[4]
parameter  ts7 = 4'b0100 ;//transmit bit[5]
parameter  ts8 = 4'b1100 ;//transmit bit[6]
parameter  ts9 = 4'b1000 ;//transmit bit[7]

/*always @ (posedge reset or posedge clk24m)
if (reset) clk_div <= 8'h00 ;
else clk_div <= (trst_ok & samp_ok) ? 8'h00 : clk_div + 8'h01 ;*/
always @ (posedge reset or posedge clk24m)
if (reset) clk_div <= 0 ;
else clk_div <= (trst_ok & samp_ok) ? 0 : clk_div + 1 ;

assign trst_ok = (clk_div[7:4] == 4'hc) ;

assign samp_ok = (clk_div[3:0] == 4'hf) ;

always @ (posedge reset or posedge clk24m)
if (reset) urx_st <= rs0 ;
else if (samp_ok) urx_st <= new_rst ;

always @ (urx_st or samp_cunt or symb_cunt or uart_in)
case(urx_st)
rs0 : new_rst = uart_in ? rs0 : rs1 ;
rs1 : new_rst = (samp_cunt == 4'hb) ? rs2 : (samp_cunt > 4'h6) ? rs1 : uart_in ? rs0 : rs1 ;  
rs2 : new_rst = (symb_cunt == 4'h8) ? rs0 : rs3 ;
default : new_rst = (samp_cunt == 4'hb) ? rs2 : rs3 ;
endcase

always @ (posedge reset or posedge clk24m)
if (reset) samp_cunt <= 4'h0 ;
else if (samp_ok) samp_cunt <= (urx_st == rs0) ? 4'h0 
:(samp_cunt == 4'hc) ? 4'h0 : samp_cunt + 4'h1 ;

always @ (posedge reset or posedge clk24m)
if (reset) symb_cunt <= 4'h0 ;
else if (urx_st == rs0) symb_cunt <= 4'h0 ; 
else if ((urx_st == rs2) && (samp_ok == 'b1))
symb_cunt <= (symb_cunt == 4'h8) ? 4'h0 : symb_cunt + 4'h1 ;

always @ (posedge reset or posedge clk24m)
if (reset) ml_count <= 4'h1 ;
else if (samp_ok) ml_count <= (urx_st == rs2) ? 4'h1 
: ml_count + {3'h0,uart_in} ;

assign ml_symb = ml_count[3] ? 'b1 : (ml_count == 4'h7) ? uart_in : 'b0 ;

always @ (posedge reset or posedge clk24m)
if (reset) urx_data <= 7'h00 ;
else if (rx_dt_sft_en) urx_data <= {ml_symb, urx_data[7:2]} ;

assign rx_dt_sft_en = (urx_st == rs2) && (samp_ok == 'b1) ; 
//When set launch the shifting from ml_count to urx_data
assign u2ii_enb = (symb_cunt == 8) ? rx_dt_sft_en : 'b0 ; 
//When set launch the transfer to iic control reg

always @ (posedge reset or posedge clk24m)
if (reset) utx_st <= ts0 ;
else utx_st <= new_tst ;

always @ (posedge reset or posedge clk24m)
if (reset) tx_samp_cunt <= 0 ;
else if (data_rdy) tx_samp_cunt <= 8'hff ;
else tx_samp_cunt <= symb_end ? 8'h00 : tx_samp_cunt + 8'h01 ;

assign symb_end = (tx_samp_cunt == 207) ;

always @ (utx_st or data_rdy or symb_end or add_buf)
case(utx_st)
ts0 : new_tst = (data_rdy && add_buf[7]) ? ts1 : ts0 ;
ts1 : new_tst = symb_end ? ts2 : ts1 ;
ts2 : new_tst = symb_end ? ts3 : ts2 ;
ts3 : new_tst = symb_end ? ts4 : ts3 ;
ts4 : new_tst = symb_end ? ts5 : ts4 ;
ts5 : new_tst = symb_end ? ts6 : ts5 ;
ts6 : new_tst = symb_end ? ts7 : ts6 ;
ts7 : new_tst = symb_end ? ts8 : ts7 ;
ts8 : new_tst = symb_end ? ts9 : ts8 ;
default : new_tst = symb_end ? ts0 : ts9 ;
endcase

//assign uart_out =(utx_st == ts0) ? 'b1 : (utx_st == ts1) ? 'b0   
assign uart_out = uart_loop ? uart_in : (utx_st == ts0) ? 'b1 : (utx_st == ts1) ? 'b0 
: (utx_st == ts2) ? recv_data[0] : (utx_st == ts3) ? recv_data[1]
: (utx_st == ts4) ? recv_data[2] : (utx_st == ts5) ? recv_data[3] 
: (utx_st == ts6) ? recv_data[4] : (utx_st == ts7) ? recv_data[5]
: (utx_st == ts8) ? recv_data[6] : recv_data[7] ;

///////////////////////////////////////////////////

always @ (posedge reset or posedge clk24m)
if (reset) data_buf <= 8'h00 ;
else if (u2ii_enb) data_buf <= (urx_data[7:6] != 2'b01) ? data_buf 
: urx_data[5] ? {urx_data[4:1],data_buf[3:0]} : {data_buf[7:4],urx_data[4:1]};

always @ (posedge reset or posedge clk24m)
if (reset) add_buf <= 8'h00 ;
else if (u2ii_enb) add_buf <= (urx_data[7:6] != 2'b00) ? add_buf 
: urx_data[5] ? {urx_data[4:1],add_buf[3:0]} : {add_buf[7:4],urx_data[4:1]};

always @ (posedge reset or posedge clk24m)
if (reset) comd_flag <='b0 ;
else if (u2ii_enb) comd_flag <= (urx_data[7:6] == 2'b11) ? 'b1 : comd_flag ;
else if (data_rdy) comd_flag <= 'b0 ;

always @ (posedge reset or posedge clk24m)
if (reset) dev_add <= 3'b000 ;
else if (u2ii_enb) dev_add <= (urx_data[7:6] == 2'b11) ? urx_data[3:1] : dev_add ;

//pay attention to data_rdy duration 

//Ready for I~2 operation
//6 state needed -- Idle, Start , Command, Address, Data, Stop 

parameter  idle = 3'b000 ;
parameter  star = 3'b001 ;
parameter  comd = 3'b011 ;
parameter  addr = 3'b010 ;
parameter  data = 3'b110 ;
parameter  stop = 3'b100 ;


assign data_okb = (iic_state == data);

always @ (posedge reset or posedge clk24m)
if (reset) iic_div <= 6'h00 ;
else iic_div <= iic_op_enb ? 0 : iic_div + 6'h01 ;
             
assign iic_op_enb = (iic_div == 6'h3f) ; //4 time faster than 100khz 

always @ (posedge reset or posedge clk24m)
if (reset) iic_state <= idle ;  //Idle when reset 
else if (iic_op_enb) iic_state <= new_state ;   //000 for Idle,  001 for Start, 011 for Command,  010 for Address, 110 for Data, 100 for Stop

always @ (iic_state or comd_flag or low_cunt or bit_cunt 
or sda_buf or phas_end)
case(iic_state) 
idle : new_state = comd_flag ? star : idle ;
star : new_state = (low_cunt == 2'b11) ? comd : star ; 
comd : new_state = (phas_end == 1'b0) ? comd 
: (sda_buf == 'b1) ? stop : (cyc_num[0] == 1'b1) ? data : addr ; //When operation fails stop the current operation and try a new one
addr : new_state = (phas_end != 1'b1) ? addr : 
(cyc_num[1] == 1'b1) ? stop : (sda_buf == 'b0) ? data : stop;
data : new_state = (phas_end == 1'b1) ? stop : data ; //Whether the operation succeeded or not, the state will transit
default : new_state = (low_cunt == 2'b11) ? idle : stop ;
endcase

always @ (posedge reset or posedge clk24m)
if (reset) sda_buf <= 'b0 ;
else if (low_cunt == 2'b01) sda_buf <= (sda !== 1'b0) ;

always @ (posedge reset or posedge clk24m)
if (reset) low_cunt <= 2'b00 ;
else if (iic_state == idle) low_cunt <= 2'b00 ;
else if (iic_op_enb) low_cunt <= low_cunt + 2'b01 ;

always @ (posedge reset or posedge clk24m)
if (reset) bit_cunt <= 4'h0 ;
else if (iic_state == 3'b001) bit_cunt <= 4'h0 ;
else if ((iic_op_enb=='b1)&&(low_cunt == 2'b11)) 
bit_cunt <= (bit_cunt == 4'h8) ? 4'h0 : bit_cunt + 4'h1 ;

assign sda = (iic_state == 3'b000) ? 'bz 
: ((iic_state == 3'b001) && (low_cunt[1] == 'b0)) ? 'bz 
: ((iic_state == 3'b001) && (low_cunt[1] == 'b1)) ? 'b0 
: ((iic_state == 3'b100) &&(low_cunt[1]  =='b0))  ? 'b0 
: ((iic_state == 3'b100) &&(low_cunt[1]  =='b1))  ? 'bz 
: sda_data ? 'bz : 'b0 ;
//assign sda_dat = (iic_state == 011) ?

always @ (posedge reset or posedge clk24m)
if (reset) cyc_num <= 2'b00 ;
else if ((u2ii_enb == 1'b1) && (urx_data[7:6] == 2'b11)) 
cyc_num <= add_buf[7] ? 2'b10 : 2'b00 ;
else if (data_rdy == 1'b1) cyc_num <= 2'b00 ;
else if ((iic_state == addr)&&(phas_end == 1'b1)
&&(sda_buf == 1'b0)&& (iic_op_enb == 1'b1)) 
cyc_num <= (cyc_num == 2'b00) ? 2'b00 : cyc_num + 2'b11 ;

assign phas_end = (bit_cunt != 4'h8) ? 1'b0 : (low_cunt == 2'b11) ;
 
assign data_rdy = (iic_op_enb != 1'b1) ? 1'b0 
: (iic_state != data) ? 1'b0 : (phas_end == 1'b0) ? 1'b0 
: (add_buf[7] == 1'b0) ? (sda_buf == 1'b0) : 'b1 ; 

assign comm_data = {4'b1010, dev_add, cyc_num[0]} ;

assign sda_data = (bit_cunt[3]) ? 'b1 
: (iic_state == comd) ? comm_data[7-bit_cunt[2:0]] 
: (iic_state == addr) ? add_buf[7-bit_cunt[2:0]] 
: add_buf[7] ? 'b1 : data_buf[7-bit_cunt[2:0]]; 

assign scl = (iic_state == idle) ? 'bz 
: ((iic_state == star) && (low_cunt < 2'b11)) ? 'bz
: ((iic_state == star) && (low_cunt > 2'b10)) ? 'b0 
: ((iic_state == stop)&& (low_cunt > 2'b00)) ? 'bz 
: ((iic_state == stop)&& (low_cunt < 2'b01)) ? 'b0
: (low_cunt[1] != low_cunt[0]) ? 'bz : 'b0 ;

always @ (posedge reset or posedge clk24m)
if (reset) recv_data <= 8'h00 ;
else if (iic_op_enb && add_buf[7]&&(iic_state == 3'b110) && (low_cunt == 2'b11) && (!bit_cunt[3])) recv_data <= {recv_data[6:0],sda_buf} ;//{recv_data[6:0],sda} ;

assign dat_req = (iic_state != data) ? 4'b0 : (bit_cunt[3]) ? 4'h0 : (add_buf[7] == 1'b0)? 4'h0 : bit_cunt + 4'h1 ;

assign ack_req = (bit_cunt != 4'h8) ? 1'b0 
: (iic_state == comd) ? 1'b1 
: (iic_state == addr) ? 1'b1 
: (iic_state == data) ? ~add_buf[7] : 1'b0 ;

endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -