OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 14892|回复: 7

求助:关于verilog中语句时序问题

[复制链接]

5

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-10-25
在线时间
5 小时
发表于 2012-10-25 22:35:56 | 显示全部楼层 |阅读模式

各位大神,菜鸟小弟我有个问题急需大家帮忙。

在always 语句下有如下情况:

...

 if(clk_bps)

  begin
          num <= num+1'b1;
          case (num)
                  4'd0: rs232_tx_r <= 1'b0;  //发送起始位
                  4'd1: rs232_tx_r <= tx_data[0]; //发送bit0
                  4'd2: rs232_tx_r <= tx_data[1]; //发送bit1
                  4'd3: rs232_tx_r <= tx_data[2]; //发送bit2
                  4'd4: rs232_tx_r <= tx_data[3]; //发送bit3
                  4'd5: rs232_tx_r <= tx_data[4]; //发送bit4
                  4'd6: rs232_tx_r <= tx_data[5]; //发送bit5
                  4'd7: rs232_tx_r <= tx_data[6]; //发送bit6
                  4'd8: rs232_tx_r <= tx_data[7]; //发送bit7
                  4'd9: rs232_tx_r <= 1'b1; //发送结束位
                  default: rs232_tx_r <= 1'b1;
            endcase
    end
   else if(num==4'd11) num <= 4'd0;

第一个问题:如果上述语句中num初始值为0,当clk_bps为真时。那case中为0的语句还执行吗?即num <= num+1'b1;先执行再执行case还是同时执行?

第二个问题:本语句来自特权同学的串口发送语句,想问num在定义为reg类型初始值为x,为什么可以不初始化为0便能正确执行发送8位数据?(补充:在整个串口发送程序中如果clk_bps不为真时,也没有复位信号时,num一直为x,为什么程序能正常运行?)



 

我的以为只是我以为...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

25

主题

106

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
231
金钱
231
注册时间
2012-8-7
在线时间
1 小时
发表于 2012-10-25 23:52:36 | 显示全部楼层
楼主应该是说仿真器的运行吧,若是仿真器,第一个问题case 0语句要执行的,因为你用的是“<=”赋值方式,仿真器会先计算完所有的结果,最后一次性赋值。至于第二个问题没有看明白(像你说的clk_bps如果不为真的话,我理解为是不可能发送数据的)。
如果楼主是直接配置FPGA,那么就不存在“语句执行”的概念了,你可以在Quartus下看看这段代码生成的RegNetlist,num应该综合成了一个带有反馈加一回路的寄存器,而case语句里生成的都是组合逻辑,且其输入端就是num寄存器的输出端。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165353
金钱
165353
注册时间
2010-12-1
在线时间
2108 小时
发表于 2012-10-26 00:10:04 | 显示全部楼层
回复【楼主位】JI:
---------------------------------
第一个,不会执行.
第二个,不解.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-10-25
在线时间
5 小时
 楼主| 发表于 2012-10-26 21:06:31 | 显示全部楼层
回复【4楼】keyway:
---------------------------------
module my_uart_tx(
clk,rst_n,
rx_data,rx_int,rs232_tx,
clk_bps,bps_start
);

input clk; // 50MHz主时钟
input rst_n; //低电平复位信号
input clk_bps; // clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
input[7:0] rx_data; //接收数据寄存器
input rx_int; //接收数据中断信号,接收到数据期间始终为高电平,在该模块中利用它的下降沿来启动串口发送数据
output rs232_tx; // RS232发送数据信号
output bps_start; //接收或者要发送数据,波特率时钟启动信号置位

//---------------------------------------------------------
reg rx_int0,rx_int1,rx_int2; //rx_int信号寄存器,捕捉下降沿滤波用
wire neg_rx_int; // rx_int下降沿标志位

always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
rx_int0 <= 1'b0;
rx_int1 <= 1'b0;
rx_int2 <= 1'b0;
end
else begin
rx_int0 <= rx_int;
rx_int1 <= rx_int0;
rx_int2 <= rx_int1;
end
end

assign neg_rx_int =  ~rx_int1 & rx_int2; //捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期

//---------------------------------------------------------
reg[7:0] tx_data; //待发送数据的寄存器
//---------------------------------------------------------
reg bps_start_r;
reg tx_en; //发送数据使能信号,高有效
reg[3:0] num;

always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
bps_start_r <= 1'bz;
tx_en <= 1'b0;
tx_data <= 8'd0;
end
else if(neg_rx_int) begin //接收数据完毕,准备把接收到的数据发回去
bps_start_r <= 1'b1;
tx_data <= rx_data; //把接收到的数据存入发送数据寄存器
tx_en <= 1'b1; //进入发送数据状态中
end
else if(num==4'd11) begin //数据发送完成,复位
bps_start_r <= 1'b0;
tx_en <= 1'b0;
end
end

assign bps_start = bps_start_r;

//---------------------------------------------------------
reg rs232_tx_r;

always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
num <= 4'd0;
rs232_tx_r <= 1'b1;
end
else if(tx_en) begin
if(clk_bps) begin
num <= num+1'b1;
case (num)
4'd0: rs232_tx_r <= 1'b0;  //发送起始位
4'd1: rs232_tx_r <= tx_data[0]; //发送bit0
4'd2: rs232_tx_r <= tx_data[1]; //发送bit1
4'd3: rs232_tx_r <= tx_data[2]; //发送bit2
4'd4: rs232_tx_r <= tx_data[3]; //发送bit3
4'd5: rs232_tx_r <= tx_data[4]; //发送bit4
4'd6: rs232_tx_r <= tx_data[5]; //发送bit5
4'd7: rs232_tx_r <= tx_data[6]; //发送bit6
4'd8: rs232_tx_r <= tx_data[7]; //发送bit7
4'd9: rs232_tx_r <= 1'b1; //发送结束位
  default: rs232_tx_r <= 1'b1;
endcase
end
else if(num==4'd11) num <= 4'd0; //复位
end
end

assign rs232_tx = rs232_tx_r;

endmodule




不好意思麻烦请您看下这个串口发送数据的程序,rx_int这个是用来触发本程序执行发送数据,就上述中case是在NUM执行之后再执行吗?就是说不会有num=0这个数据发,那串口起始位不是没有发送了吗?为什么?

这个程序是吴厚航,也就是特殊同学,可能会听说过,写过一本书叫《深入浅出玩转fpga》,他写的串口程序,下载后是可以正常运行的?


谢谢您了哈
我的以为只是我以为...
回复 支持 反对

使用道具 举报

5

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-10-25
在线时间
5 小时
 楼主| 发表于 2012-10-26 21:20:49 | 显示全部楼层
回复【2楼】草尼玛:
---------------------------------
第二个问题我简化一下:
请您先看这个最简单的计数器程序(我下载试了试正确的):
module part_1(
              cout,rco,
              clk,reset_n
              );
input   clk;
input   reset_n;
output  reg [3:0] cout;
output  reg rco;



always @(negedge clk or  negedge reset_n)
 begin
     if(!reset_n)
     begin
        rco =1'b0;
        cout =4'b0000;
     end
    else if(cout == 4'b1001)begin
              cout=4'b0000;
              rco=1'b1;
         end
    else
        begin
        cout=cout+1;
        rco=1'b0;
        end
end

endmodule


然后,我不明白的是:verilog语言书上在定义reg类型时,默认都是x(夏宇闻老师翻译的那本国外教材书上有),比如这个cout,我们并没有给它初始位0,下载后也没有对rst_n进行复位,如果按照默认值x,那这个计数器不是不能正常工作了吗?


可能就这个点我理解得不够好,才对第一个问题产生更多的疑惑,第一个问题中num跟计数器cout一样没有初始化,而且我发现关于这些计数的reg类型变量在很多程序中都没有初始化,程序都能正常运行,这是为什么?求大神指教。

第二点就是,书上说begin—end之间的语句如果是阻塞赋值就顺序执行,非阻塞赋值《=是并发执行,也就是说num《=num+1和case同时执行是吗?


谢谢您了^ ^
我的以为只是我以为...
回复 支持 反对

使用道具 举报

5

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-10-25
在线时间
5 小时
 楼主| 发表于 2012-10-26 21:24:08 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
为什么不会执行,他们说会啊,这个是来时串口发送程序中的一部分,这个程序是正确发送数据给串口的,说明num=0执行了,不然是发送不出起始位的,求指教....
我的以为只是我以为...
回复 支持 反对

使用道具 举报

25

主题

106

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
231
金钱
231
注册时间
2012-8-7
在线时间
1 小时
发表于 2012-10-27 09:42:30 | 显示全部楼层
回复【6楼】JI:
---------------------------------
你那个说的是仿真器,夏宇闻老师的书大多都没有涉及到硬件实现,当你的代码生成配置文件下载到可编程逻辑器里就不存在什么x了,要么是0要么是1。FPGA中,verilog生成的是数字电路,并不是C语言那样生成可执行文件,OK?
第二个问题,还是因为你没有理解仿真器与配置FPGA后的区别。在FPGA中,如果是用“<=”对某个变量a赋值,只要后面另一个变量有对变量a做引用,那么a就必须要综合成寄存器,所以说时序电路一般都用“<=”赋值,如果仿真器(如modelsim)要来仿真这个行为,就说“会先把所有语句计算完后再一次性赋值”,建议你先搞懂FPGA的基本原理,这两个问题就都是浮云了
回复 支持 反对

使用道具 举报

5

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2012-10-25
在线时间
5 小时
 楼主| 发表于 2012-10-27 16:39:16 | 显示全部楼层
回复【8楼】草尼玛:
---------------------------------
谢了...
我的以为只是我以为...
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 12:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表