OpenEdv-开源电子网

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

LED实验怪异的问题。。。求助啊。。。

[复制链接]

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
发表于 2012-6-4 12:48:09 | 显示全部楼层 |阅读模式
最近做数电课设,让用FPGA做东西。。。我看同学用原理图输入法来做挺蛋疼的,
所以就决定用代码来做这鸟东西,毕竟我对代码特别有亲切感,结果没想到,会这么蛋疼。。。

我上传工程代码,请大家帮忙看看是什么问题,

目录顶层模块是文件 led_water.v  里 的 led_water,目前实现的功能是三个LED像一个计数器一样,每 秒加1,

问题就出现在这里:
有两段代码:
     /*
        clk_div #(25_000_000, 25) clk_div_inst(        // 分频实例, 25M 分频,25的计数器位宽
                  .clk_in (clk_in)
                , .out_pulse (led_clk)
        );
        */
        ///*
        clock_division #(26)  clk_div_inst(        // 分频实例, 25M 分频,25的计数器位宽
                  .clk_in (clk_in)
                , .out_pulse (led_clk)
                , .div_factor (26'd50_000_000)
        );
        //*/

其中第一段是好用的,如果把第一段注释了,换成第二段,下载测试后发现LED计数器就会从原来的三位变成两位。。。第0位完全被忽略了。。。

搞了好久都不知道是什么原因,所以希望大家帮忙看看

led_step_motor.zip

473.67 KB, 下载次数: 546

https://github.com/roxma
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

16

主题

71

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
275
金钱
275
注册时间
2015-7-16
在线时间
14 小时
发表于 2016-9-14 08:46:24 | 显示全部楼层
代码写的真烦  Verilog这么写  我都懒得看
回复 支持 1 反对 0

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2012-6-4 13:14:24 | 显示全部楼层
我发现要是把第二块代码的实例改成
clock_division #(25)  clk_div_inst( // 分频实例, 25M 分频,25的计数器位宽
 .clk_in (clk_in)
, .out_pulse (led_clk)
, .div_factor (25'd10_000_000)
);

也就是26位改成25位,就没有上面说的问题了,那个 参数只不过是分频数的位宽啊。。。为什么。。。会这样。。。


或者把 clock_division 模块的定义中的
module clock_division(
 input  clk_in
, output out_pulse
, input[BIT_WIDTH-1:0] div_factor); // 输出脉冲

parameter BIT_WIDTH = 26; // the bit-width of the counter
reg [BIT_WIDTH-1: 0] cnt; 

always@ (posedge clk_in) begin
if(cnt == div_factor-1)
cnt <= 0;
else
cnt <= cnt+1'b1;
end
assign out_pulse = (cnt == div_factor-1)?1'b1:1'b0;
endmodule

那两个加粗的定义改成
input[BIT_WIDTH:1] div_factor);
reg [BIT_WIDTH: 1] cnt; 
这样不管用25还是26都能工作。。。

为什么。。。难道是我verilog语法不过关导致的问题吗?


https://github.com/roxma
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2012-6-4 23:37:27 | 显示全部楼层
哎,现在还是有问题啊,换了块同学的别的型号的板子,问题依旧。。。
https://github.com/roxma
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2012-6-4 23:40:51 | 显示全部楼层
这东西我玩的少...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2012-6-5 00:48:39 | 显示全部楼层
玩单片机的时候遇到的最诡异的事情基本上是由指针或者数组越界导致的,

FPGA这种问题真是奇怪了,我几乎可以确定代码是没问题的,

那段代码刚写好的时候也遇到了一样的问题,后来把 Quartus II 的版本换成最新 的,问题就没有了,

然后在改进的时候问题又出现了,实在是让人不解啊
https://github.com/roxma
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2012-6-5 15:30:02 | 显示全部楼层
唉,好无助啊。。。问题似乎是解决了,可是还是不明白为什么。。。

问题代码似乎是 /*---*/ 包围的地方,有三种方案,看注释,不知没有有人能帮我解释一下?

module ClockDivision(
 input  clk
, input rst_n_d /* 异步清零 */
, input[CLK_DIV_BIT_WIDTH:1] div_factor
, output out_pulse /* 输出时钟脉冲 */
);

parameter CLK_DIV_BIT_WIDTH = 32; // the bit-width of the counter

wire counter_rst_n;
wire [CLK_DIV_BIT_WIDTH:1]count;
Counter #(CLK_DIV_BIT_WIDTH) ClockDivision_Counter(
 .clk (clk)
, .rst_n_d (counter_rst_n)
, .count (count)
);
reg out_pulse_r; /* 输出脉冲寄存器 */
always@ (posedge clk) begin 
/* 当上升沿之前计数到 div_factor-1'b1,就可以输出脉冲了 */
out_pulse_r <= ( (count+1'b1) == div_factor)?1'b1:1'b0 ;
end
/* 当计数到设定的值的时候,使能异步复位,直接清零 */
assign counter_rst_n = (!rst_n_d)?1'b0 (count == div_factor)?1'b0:1'b1 );
/*---------------------------------------------------------------*/
/* 为什么这个会有问题呢,我想在时钟下降沿清零啊!!!为什么呢?为什么呢? */
//assign out_pulse = clk?out_pulse_r:1'b0;
/* 如果分频系数为 1,直接输出时钟,这种方式是可行的 */
wire sel = div_factor==1?1'b1:1'b0;
assign out_pulse = sel?clkut_pulse_r;
/* 这种方式在分频系数为 1 的时候输出是不会跳的 */
//assign out_pulse = out_pulse_r;
/*---------------------------------------------------------------*/
endmodule




LED_StepMotor.zip

509.98 KB, 下载次数: 488

https://github.com/roxma
回复 支持 反对

使用道具 举报

1

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2012-6-11
在线时间
8 小时
发表于 2012-6-11 23:42:31 | 显示全部楼层
你还在做吗?你的代码是有问题的。
第一、参数表中的位索引(Index)不要从N到1,正确的写法是input[BIT_WIDTH-1:0] div_factor,否则不能保证正确;
第二、若要使用异步清零,需要在敏感列表中添加如下内容:@(posedge CLK or negedge RST),然后在下面用
if(~RST)表示复位命令。这样就能使用DFF的RST端了,综合器会自动综合成异步复位或置位(根据你的数据而定,如果为1则为SET);
第三、参数表不要直接使用数字#(a,b)的方式写,而是使用#(.Parameter1(a),.Parameter2(b))的方式来写。因此,clock_division #(26)是肯定不工作的,因为此时你的分频数被定义成了26,但是位宽变成了默认位宽。
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2012-6-12 10:17:17 | 显示全部楼层
回复【7楼】 wye1102 :
---------------------------------
谢谢你的回复,其实我并不认为我的代码在功能和语法上是有问题的,
关于第一点,我能确定是没有问题的,这一点我是看过生成的 RTL 验证过的,但代码里风格不统一不是个好习惯。
而第二点,其实我在计数器模块的内部的代码是有这样写的。
关于第三点,我看过生成的RTL,这样写是没有问题的,只要顺序没弄错。不过要谢谢你,因为我一直不知道有这种写法。

不过我在 5 楼上传的代码还是有一些问题,我这个帖子里的问题的原因都是直接把组合逻辑用在了输出端上,受到了了竞争冒险现象的影响,这个是我写 testbench 仿真看波形图后发现的,波形可能会在极短的时间里做出不应该有的动作(特别是像与门这类东西,不过数据选择器在普通情况下是可靠的,也就是那个 “?” 运算符生成的电路),后来我在输出端后再加一个时钟控制的锁存器来进行同步控制,波形图就相当漂亮了。

直接用组合逻辑是不可靠的。特别是在这一级输出的跳变沿是作为下一级的触发信号的时候,就可能导致我这几天焦头烂额的悲剧!

https://github.com/roxma
回复 支持 反对

使用道具 举报

1

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2012-6-11
在线时间
8 小时
发表于 2012-6-12 17:18:00 | 显示全部楼层
你还是写得少。我现在一般不后仿真,太浪费时间。但是我能保证我的程序前仿没问题,下进去就没问题,你如果不好好改改,还真做不到呵呵。需要时间和代码量的积累。
你的语法要尽量向大家常用的方向发展。有些细节部分还真得注意。另外就是FPGA尽量只做时序逻辑,尽量不要出现纯组合。等你以后开始写Constraint之后你就会明白这些。慢慢的你自己都会开始采用一两种固定风格了。我现在是用我自己定义的规范:

一、接口命名
1、内部逻辑
内部逻辑仅用于内部逻辑连接。不可直接用于IO。
输入:int_in_[Interface Name]
输出:int_out_[Interface Name]
内部输入输出全部为同步逻辑。
2、IO逻辑
IO逻辑在内部使用寄存器缓冲,尽量不使用于内部逻辑。
输入:port_in_{sync|async}_[Interface Name]
异步输入必须使用寄存器缓冲,同步输入必须使用输入时钟。时钟输入不需 要接其它东西。
输出:port_out_{sync|async}_[Interface Name]
显式指明输出类型,便于接口定义和处理。
双向:port_io_{sync|async}_[Interface Name]
二、状态机命名
rs_[State Machine Name]
三、计数器命名
rc_[Counter Name]
四、寄存器命名
r_[Register Name]
r_{in|out}_[Register Name]
r_[IO/Int Interface Full Name]_delay
五、线命名
w_[Wire Name]
w_{in|out}_[Wire Name]
w_[IO/Int Interface Full Name]_edge
六、时钟命名
GCLK[Clock Name]
七、接口连接
int to port:使用寄存器输出
port to int:使用寄存器输入(除时钟和复位)
port to port:直接相连
int to int:直接相连

当然不全面,但是至少我写代码和看自己的代码不会出任何问题了。唯一的缺点是Verilog没有代码管理功能,寄存器等等一多就不好管理了。
回复 支持 反对

使用道具 举报

21

主题

135

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
238
金钱
238
注册时间
2011-4-12
在线时间
0 小时
发表于 2012-6-13 12:45:58 | 显示全部楼层
回复【9楼】wye1102:

---------------------------------
楼上牛人!!!以后多多指教~~
自信人生一百年
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2012-6-13 13:34:20 | 显示全部楼层
回复【9楼】wye1102:
---------------------------------

嗯,确实很少写 verilog 代码,我的 FPGA 连入门水平都算不上,
因为要做数电课程设计我才花时间在这上面的,本来我也不打算仿真的,反正乱试几次然后就可以运行了,因为报告上要求要做仿真我才写的,然后才发现波形还是有些问题。从严格的意义上讲,仿真是很有意义的。很多东西在一开始测试不严格就会给后面的事情带来巨大的灾难,关于这点在单片机上我已经吃过不止一次苦头了。不过比较郁闷,百度谷歌了好久,居然没找到跟我遇到同样问题的。。。我看过的入门教程也没特别说明这个问题。。。

至于代码风格,也没什么标准,我认为关键是做到自己的风格统一就行。刚开始学,就没必要那么注重习惯了,写久了风格自然就出来了。

这些东西确实需要积累,还需要大家多多指教啊
https://github.com/roxma
回复 支持 反对

使用道具 举报

9

主题

53

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
372
金钱
372
注册时间
2016-8-15
在线时间
55 小时
发表于 2016-9-8 11:41:23 | 显示全部楼层
我是来看pony的
祝中国健儿奥运好成绩
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2195
金钱
2195
注册时间
2012-2-8
在线时间
34 小时
 楼主| 发表于 2016-9-14 12:55:55 | 显示全部楼层
本帖最后由 Pony279 于 2016-9-14 12:57 编辑
清风揽月shine 发表于 2016-9-14 08:46
代码写的真烦  Verilog这么写  我都懒得看

收起你那些关于代码的风格的执念。

这里整个实验的代码不过 36 行代码,可以说是超级少的代码了。我只是做个实验,从来没打算写一个巨大的工程,我只是想 get the shit done,谁关心什么代码风格?难道我还要找本 verilog 代码风格指南一字一句读完才开始写  LED 闪烁灯?你是出来搞笑的吧?

每个人都有自己的风格,这个是非常主观的,如果没有在一个受规范约束的团队,而且当时也没有建立起有实际影响力行业标准,也请收起那些代码风格的执念。

我也喜欢优雅的代码,但是我讨厌这种跑题的无意义争论。
https://github.com/roxma
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 19:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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