完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
各位大神,菜鸟小弟我有个问题急需大家帮忙。
在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,为什么程序能正常运行?) |
|
相关推荐
8个回答
|
|
楼主应该是说仿真器的运行吧,若是仿真器,第一个问题case 0语句要执行的,因为你用的是“<=”赋值方式,仿真器会先计算完所有的结果,最后一次性赋值。至于第二个问题没有看明白(像你说的clk_bps如果不为真的话,我理解为是不可能发送数据的)。
如果楼主是直接配置FPGA,那么就不存在“语句执行”的概念了,你可以在Quartus下看看这段代码生成的RegNetlist,num应该综合成了一个带有反馈加一回路的寄存器,而case语句里生成的都是组合逻辑,且其输入端就是num寄存器的输出端。 |
|
|
|
|
|
|
|
|
|
|
|
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》,他写的串口程序,下载后是可以正常运行的? 谢谢您了哈 |
|
|
|
第二个问题我简化一下:
请您先看这个最简单的计数器程序(我下载试了试正确的): 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同时执行是吗? 谢谢您了^ ^ |
|
|
|
为什么不会执行,他们说会啊,这个是来时串口发送程序中的一部分,这个程序是正确发送数据给串口的,说明num=0执行了,不然是发送不出起始位的,求指教....
|
|
|
|
你那个说的是仿真器,夏宇闻老师的书大多都没有涉及到硬件实现,当你的代码生成配置文件下载到可编程逻辑器里就不存在什么x了,要么是0要么是1。FPGA中,verilog生成的是数字电路,并不是C语言那样生成可执行文件,OK?
第二个问题,还是因为你没有理解仿真器与配置FPGA后的区别。在FPGA中,如果是用“<=”对某个变量a赋值,只要后面另一个变量有对变量a做引用,那么a就必须要综合成寄存器,所以说时序电路一般都用“<=”赋值,如果仿真器(如modelsim)要来仿真这个行为,就说“会先把所有语句计算完后再一次性赋值”,建议你先搞懂FPGA的基本原理,这两个问题就都是浮云了 |
|
|
|
谢了...
|
|
|
|
只有小组成员才能发言,加入小组>>
2862 浏览 3 评论
27626 浏览 2 评论
3435 浏览 2 评论
3958 浏览 4 评论
基于采用FPGA控制MV-D1024E系列相机的图像采集系统设计
2304 浏览 3 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 19:37 , Processed in 0.835684 second(s), Total 92, Slave 72 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号