学习笔记 : 三态门写法技巧

三态门原理结构图:

(1)、FPGA对外只有一个信号data

(2)、内部有三个信号 wr_en 、wr_data 和 rd_data

 

先看下面这段很不规范代码,

(1)、always模块里面的信号尽量不要有赋高阻 "z", 只能赋“0” 或赋 “1”; 

(2)、always 模块里面尽量不要出现双向信号赋值

(3)、当使用signaltap仿真时,难以定位,因always模块内部有赋高阻的情况,那么当某一时data = 1'b0时,可能就不知道data = 1'b0是从哪里来的,是FPGA内部产生的,还是FPGA外部驱动产生的

 1 inout    data;  //方向是双向
 2 /*******************************************************************************/
 3 //在always 里面的信号要么赋"0",要么赋"1",不要出现赋“z”
 4 //当使用signaltap仿真时,难以定位,因always模块内部有赋高阻的情况,那么当某一时data = 1'b0时,
 5 //可能就不知道data = 1'b0是从哪里来的,是FPGA内部产生的,还是FPGA外部驱动产生的
 6 always @(posedge clk or negedge rst_n)begin
 7     if(!rst_n)begin
 8         data <= 1'bz;  //不建议在信号模块里赋高阻 ,避免这种写法
 9     end
10     else if(a==1 && b==1) begin
11         data <= 1'b1;
12     end
13     else if(a==1 && c==1)begin
14         data <= 1'b0;
15     end
16     else begin
17         data <= 1'bz; //不建议在信号模块里赋高阻
18     end
19 end
20 
21 always @(posedge clk or negedge rst_n)begin
22     if(!rst_n)begin
23         d <= 0;
24     end
25     else begin
26         d <= data; //这里的data是个双向信号
27     end
28 end
29 
30 /*******************************************************************************/

 

规范代码如下:

 1 /*******************************************************************************/
 2 inout    data;  //方向是双向'
 3 
 4 //控制三态门使能
 5 always @(posedge clk or negedge rst_n)begin
 6     if(!rst_n)begin
 7         wr_en <= 1'b0;
 8     end
 9     else if(a==1 && (b==1 || c==1))begin
10         wr_en <= 1'b1;    //打开三态门
11     end
12     else begin
13         wr_en <= 1'b0;    //其他条件下关闭三态门
14     end
15 end
16 
17 //给输出的赋值,要取决于三态门的关闭或打开,只有在三态门打开时,才会送出
18 always @(posedge clk or negedge rst_n)begin
19     if(!rst_n)begin
20         wr_data <= 1'b0;
21     end
22     else if(a==1 && b==1)begin
23         wr_data <= 1'b1;
24     end
25     else if(a==1 && c==1)begin
26         wr_data <= 1'b0;
27     end
28     else begin
29         wr_data <= 1'b0;
30     end
31 end
32 
33 //读数据
34 always @(posedge clk or negedge rst_n)begin
35     if(!rst_n) begin
36         d <= 1'b0;
37     end
38     else begin
39         d <= rd_data;  //rd_data 是个单向信号
40     end
41 end
42 
43 //下面这段一般放在顶层模块,内部模块就都定义了成单向信号,内部模块的每个信号就都有确定值,要么是“0”,要么是“1”,不会出现高阻态
44 assign data = wr_en ? wr_data : 1'bz;
45 assign rd_data = data; 
46 /*******************************************************************************/

规范代码有点:

(1)、一个always模块里只控制一个信号,容易定位问题

(2)、always 模块里不会出现赋高阻态“z” ,信号只能赋 “0” 或 “1” ,都有明确的数值

(3)、双向的信号在顶层模块写好,内部模块就都是单向信号,要么是input 或 output

posted @ 2022-08-11 22:17  MyBooks  阅读(384)  评论(0编辑  收藏  举报