首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

三态门详解(2)

三态门详解(2)

module stm
(
i_clk,
i_rst_n,
SDA
);

input i_clk;
input i_rst_n;
inout SDA;

reg sda_en;
reg sda_out;
reg [9:0] cnt;
reg clk_out;

always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n==1'b0)
cnt <= 10'd0;
else if(cnt==10'd999)
cnt <= 10'd0;
else
cnt <= cnt + 1'b1;

always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n==1'b0)
clk_out <= 1'b0;
else if(cnt==10'd999)
clk_out <= ~clk_out;

always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n==1'b0)begin
sda_out <= 1'b0;
sda_en <= 1'b1;
end
else begin
sda_out <= clk_out;
sda_en <= 1'b0; //这里为0表示作为输入口使用
end

assign SDA = (sda_en)? sda_out:1'bz;
endmodule
当做为输入口时,我在vivado仿真脚本里添加了一个输入时钟clk_out,为了加以区别,输入口的clk_out这个的频率是计数到499就翻转而作为输出口的clk_out是计数到999才翻转,所以输人口的clk_out的频率是输出口的clk_out 的频率的两倍,代码如下:
module test_tb();
reg i_clk;
reg i_rst_n;

wire SDA;
stm u1
(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.SDA(SDA)
);

reg [9:0] cnt;
reg clk_out;

always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n==1'b0)
cnt <= 10'd0;
else if(cnt==10'd499)
cnt <= 10'd0;
else
cnt <= cnt + 1'b1;

always@(posedge i_clk or negedge i_rst_n)
if(i_rst_n==1'b0)
clk_out <= 1'b0;
else if(cnt==10'd499)
clk_out <= ~clk_out;

assign SDA = clk_out;
initial begin
i_clk = 0;
i_rst_n = 1;
#10;
i_rst_n = 1'b0;
#120;
i_rst_n = 1'b1;
end

always #40 i_clk = ~i_clk;
endmodule
SDA作为输入口时,仿真波形如下,大家可以看到当sda_en为低时,即使sda_out上面有我们之前产生的clk_out计数到999的那个频率,但SDA依然是clk_out计数到499时的频率,所以可以看出这时SDA是作为输入口使用的。
返回列表