verilog语法中的for循环的应用
module data_conv(clk,dat,units,tens,hundreds,thousands);
input clk;
input[13:0] dat; //二进制输入数据
output[3:0] units;
output[3:0] tens;
output[3:0] hundreds;
output[3:0] thousands;
reg[3:0] units_r,tens_r,hundreds_r,thousands_r; //BCD数据输出寄存器
reg[13:0] dat_r;
reg[15:0] temp; //中间寄存器
integer i;
assign units = units_r;
assign tens = tens_r;
assign hundreds = hundreds_r;
assign thousands = thousands_r;
initial temp=16'b0; //这个地方是该写在for里面还是外面?
always @(posedge clk)
begin
dat_r = dat;
for(i = 0;i < 15;i = i + 1) //循环15次,注意不是15次,因为第15次不需要修正
begin
temp = {temp[14:0],dat_r[13]}; //左移一位
if(temp[3:0] > 4'd4) //大于4,加三
temp[3:0] = temp[3:0]+4'd3;
if(temp[7:4] > 4'd4) //大于4,加三
temp[7:4] = temp[7:4]+4'd3;
if(temp[11:8] > 4'd4) //大于4,加三
temp[11:8] = temp[11:8]+4'd3;
if(temp[15:12] > 4'd4) //大于4,加三
temp[15:12] = temp[15:12]+4'd3;
dat_r=dat_r<<1; //最高变为原来dat_r的第14位
{thousands_r,hundreds_r,tens_r,units_r}={temp[14:0],dat[0]};//最后一次(第16次)不用修正
end
end
endmodule
这是一个二进制数转十进制BCD码的代码,我想实现0~9999的二进制数转换成BCD码,输入是14位的(输出肯定是16位),然后我随便给dat附了几个值,仿真了一下,但是出得结果不正确啊,难道是for语句出了问题,但是实在看不出来呢,还请高手们给以作答,谢谢。
加注: initial temp=16'b0;如上红题字该写在for里面还是外面啊,结果好像也不一样啊,但是我感觉应该写在外面呢,可是结果更不对了,每当上升沿的时候个十百千四个数就发生变化了
应该在FOR里面,如果你写外面,综合也许会出问题吧?
我见过VHDL语法里类似的初始赋值,然后再FOR运算,初始赋值包含在句子里面。
没有格式看着有点累
写在里面是怎么理解啊,感觉写在外面才是赋初值啊,写在里面,难道每来一个上升沿都赋值吗?
我仿真了,写在外面的话结果肯定不对,不是太明白。即使是写在外面的话代码仿真出来的结果也不是正确的,不知什么原因呢?求解释。
没明白您的意思呢,什么格式啊
是不是我没看懂。
你写的组合逻辑反馈,当然错啦。
组合逻辑反馈?不是吧,这个模块的功能是实现14位二进制数转十进制BCD码0~9999,用了一个移位加3的算法,算法描述如下: 以8位二进制转换为3位BCD码为例,转换步骤是:将待转换的二进制码从最高位开始左移BCD的寄存器(从高位到低位排列),每移一次,检查每一位BCD码是否大于4,是则加上3,否则不变。左移8次后,即完成了转换。需要注意的是第八次移位后不需要检查是否大于5。我用了一个for语句进行移位,但是不知道为什么,逻辑上有错误,结果不正确。
错得一塌糊涂,还是先看看课本吧。
首先initial是不可综合的,这个解释了2楼为什么要让你现在always里面,最好是提供一个复位信号来做赋初值的操作,不要用initial,这个一般只用于仿真。另外内部这个for循环更多偏向于软件设计的思想,不知道你的仿真环境是基于源代码还是综合后的网表。
我大概看了看,感觉倒是你最后一次的处理,不应该放到循环里面,应该是15次循环完成以后得到一个temp去和dat[0]进行拼接也许就是你要的结果了吧,不过这里似乎也没问题,反正你都是要最后一次的结果。就是这么写法完全都是软件设计的思想,看得人头疼。呵呵。
呵呵,谢谢前辈指导啊
我这个代码就是先进行的仿真的,所以加了initial赋值,这样的话,只进行仿真该是放到里面外面啊?还有最后一行,如果每一次都执行一次的话没有逻辑上的错误吧?我是刚刚学习verilog语言,硬件设计思想还没有渗入,呵呵,让您见笑了,谢谢您的指导
呵呵,是,谢谢批评,刚刚学习,不是太懂,还望赐教
没有像这样写过设计代码,最好还是参考可综合的风格来写,引入复位信号来实现赋初值比较好。如果一定要用initial,那就是在外面,不过没这么用过,不知道是否能够得到你要的结果。也要取决与你用什么仿真。
“没有像这样写过代码”怎么解释,是指的都是按可综合的来写吗?那做设计的时候不是都需要仿真么?怎么仿真呢?我是用modelsim仿真的,但是结果都不对,而且有输出延时很严重。 说说我的错误结果吧,我把initial写在外面,输出的个十百千位每当上升沿触发的时候都会改变,结果肯定也不正确;把initial写在外面的时候,结果就不正确了,而且延时比较严重。
还是先好好看书学习的好。
呵呵,是,谢谢
恩,如果我没想错的话,或许这就是因为硬件设计思想和软件设计思想的问题吧,
你对错误的描述也很混乱,让人搞不清楚,至少你的代码风格不严谨,所以能不能得到你希望的功能就很难说了,这个语言是描述语言,而不是设计语言,不能凭空创造没有的东西,首先要对底层的硬件电路有一个概念,什么语句会描述什么电路。
哦,是,由于刚开始学习,还没有深入的学习代码的编写风格,还需要继续学习,底层电路的基础也不是太扎实,我会努力的,谢谢您的指导。我的问题更简单的描述一下就是仿真输出的结果不正确,设置的几个值输出的结果都不对,应该是语句的逻辑有问题吧。
哦,是,由于刚开始学,还没有深入的学习代码的风格,还需继续努力,底层电路的基础知识也不是太扎实,我会努力的,谢谢您的指导。我的问题说的更简单点就是仿真的时候出来的结果不正确,设置的几个数个十百千位的BCD码都不对,可能是逻辑上的错误吧。
哦,好,谢谢您的指教。我在论坛里听到了很多关于注重综合之类的话语,我想问一下,是不是和仿真相比综合更显重要。对了,能不能给我推荐几本关于综合的教材呢,谢谢您。
谢谢前辈指导啊
注重综合是一种经验的积累,一般的书很少涉及,介绍综合工具和思想的倒是很多,但可综合代码的一般都是牛人自己的经验总结,不一定是完全可以依据的,这个需要你自己结合自己的设计来理解归纳,不要一味地相信语法书上说的都是可用的。
哦,明白了,谢谢前辈
