EPM240 求助!
我想用EPM240实现以下功能:输入:
BJ 1位
Input 21位
输出
Output 21位
逻辑
如果BJ==1
Output=Input
如果BJ==0
从低位查找输入中0的位置,根据0的位置输出。
例如:如果输入为XXXXXXXXXXXXXXXXXXXX0 则输出111111111111111111100其中X为任意值
如果输入为XXXXXXXXXXXXXXXXXX011 则输出111111111111111110011其中X为任意值
输入数据的变化频率比较低,可以不用考虑。
要求输出的信号为稳定的0V或者 3.3V,不能是脉冲。
小弟新手,也按照这逻辑写了代码,但是输出不稳定,有些输出是脉冲。论坛有朋友告诉我需要时序,我就不懂了。希望能做的大侠帮个忙!
另外因为这是公司的事,小弟可以申请个几百块的费用(不过多了就不行了:( ),有哪位大侠有兴趣留个联系方式:handshake ,感激不尽!!!
请大家一定帮帮忙啊!!!!我被蹂躏好几天了:'(:'(:'( 本帖最后由 huatong 于 2012-3-24 10:39 编辑
不知道这样可以吗?module help(clk,bj,in,out);
input clk;
input bj;
input in;
output reg out;
initial begin
out=21'hz;
end
always@(posedge clk) begin
out<=in;
if(!bj) begin
if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
else if(!in)
out<=1'b0;
end
end
endmodule 如果BJ==0
从低位查找输入中0的位置,根据0的位置输出。
例如:如果输入为XXXXXXXXXXXXXXXXXXXX0 则输出111111111111111111100其中X为任意值
如果输入为XXXXXXXXXXXXXXXXXX011 则输出111111111111111110011其中X为任意值
没看出来啥规律 yuyu87 发表于 2012-3-24 10:44 static/image/common/back.gif
没看出来啥规律
在第一个出现0的位置的下一个位置输出0 huatong 发表于 2012-3-24 10:48 static/image/common/back.gif
在第一个出现0的位置的下一个位置输出0
打了一份CPLD驱动LCD的板,明天正式开始学习CPLD
你做的板子很漂亮,致敬~ 首先感谢回复!
我感觉逻辑似乎不是我想要的,逻辑上输出只与第一个0的位置相关,而且输出一定只有两个连续的0
XXXXXXXXXXXXXXXXXXXX0 输出111111111111111111100 其中X为任意值,即一旦有0,则后续的值不再考虑
XXXXXXXXXXXXXXXXXXX01 输出111111111111111111001
XXXXXXXXXXXXXXXXXX011 输出111111111111111110011
XXXXXXXXXXXXXXXXX0111 输出111111111111111100111
XXXXXXXXXXXXXXXX01111 输出111111111111111001111
依次类推
我用过casez但输出有脉冲,不稳定
而且直接 Out<=In都不能稳定的输出,有些输出的管脚是脉冲!
个人认为:
EPM240在一个时钟周期内执行的逻辑有限,所以需要将逻辑分开,小弟水平不行,不知道如何分开。
另外有些管脚输出脉冲的原因,是否因为在一个时钟周期内逻辑没执行完,而下一个周期又重新执行,导致的输出不稳定呢?
本帖最后由 huatong 于 2012-3-24 11:01 编辑
yuyu87 发表于 2012-3-24 10:50 static/image/common/back.gif
打了一份CPLD驱动LCD的板,明天正式开始学习CPLD
你做的板子很漂亮,致敬~
谢谢,可惜程序还没有写通. 个人认为:
EPM240在一个时钟周期内执行的逻辑有限,所以需要将逻辑分开,小弟水平不行,不知道如何分开。
有限?汗~ :L frjwdcyd 发表于 2012-3-24 11:00 static/image/common/back.gif
首先感谢回复!
我感觉逻辑似乎不是我想要的,逻辑上输出只与第一个0的位置相关,而且输出一定只有两个连续 ...
应该没有错吧,只是考虑第一个0的位置,后面的都不处理啊,是if()完第一个0,后面的的就不处理了,而且一定是2个0啊(第一个出现0的位置及它的下一位与是0) 明白了,原来后面都要是1,那改一下就可以了 试试这个,随便改改不许笑啊
module help(input bj,input in,output reg out);
always@(bj or in) begin
if(bj)out<=in;
elsebegin
if(!in)
out<=21'b111111111111111111100;
else if(!in)
out<=21'b111111111111111111001;
else if(!in)
out<=21'b111111111111111110011;
else if(!in)
out<=21'b111111111111111100111;
else if(!in)
out<=21'b111111111111111001111;
.......
else if(!in)
out<=21'b001111111111111111111;
else if(!in)
out<=21'b011111111111111111111;
else
out<=21'b111111111111111111111;
end
end
endmodule huatong 发表于 2012-3-24 11:11 static/image/common/back.gif
明白了,原来后面都要是1,那改一下就可以了
我以前和你写的差不多,类似
if(!in)
out<=21'b111111111111111111100;
else if(!in)
out<=21'b111111111111111111001;
else if(!in)
out<=21'b111111111111111110011;
else if(!in)
out<=21'b111111111111111100111;
else if(!in)
out<=21'b111111111111111001111;
。。。。。。
out的前7位输出还比较稳当,但是第8位以后输出的的是脉冲,很不稳定!我也不知道是什么原因。 而且最奇怪的是,整个程序只一句
out<=in;
都不能稳定输出,现象是out的前7位输出比较稳定(0或者3.3v),但是从第8位开始 有些管脚输出的的是脉冲,很不稳定! 本帖最后由 kebaojun305 于 2012-3-24 12:21 编辑
要注意点cPLD是 并行执行的这 几个判断是同时执行的(导致你的输出有几个值是同时输出的 看布线的延时 这个就是冲突 ) 估计就是这样原因才产生的毛刺应该加个缓冲寄存器先判断最低得那个0 然后把其他位都设置成固定的数字最好在根据这个值 输出。就不会有毛刺了。 这个写法要保证输入的数据只有1个0 其他的都是1输出应该是对的如果有2个0以上的输入数据 就会有毛刺输出。
你看看综合出来的RTL图估计更好看出问题。 如果是信号有毛刺,就是各个逻辑信号因为延时差异产生竞争,如果能加个时钟,就好办多了 kebaojun305 发表于 2012-3-24 12:05 static/image/common/back.gif
要注意点cPLD是 并行执行的这 几个判断是同时执行的(导致你的输出有几个值是同时输出的 看布线的延时...
能帮忙做个简单的例子吗,新手:L
“先判断最低得那个0 然后把其他位都设置成固定的数字”这个貌似有点难,21位的组合量太大了。
而且我做个试验类似
case (in)
111111111111111111110 out<=21'b111111111111111111100
......
当in为4位时,能稳定输出,当in为16位时,输出就有脉冲了。
所以我认为EPM240是每个时钟周期进行一次计算,每次计算完都输出。
thxcai2 发表于 2012-3-24 12:12 static/image/common/back.gif
如果是信号有毛刺,就是各个逻辑信号因为延时差异产生竞争,如果能加个时钟,就好办多了 ...
输入中可以加入时钟 frjwdcyd 发表于 2012-3-24 12:05 static/image/common/back.gif
而且最奇怪的是,整个程序只一句
out
很奇怪啊,我这里看不出有毛刺啊. 本帖最后由 kebaojun305 于 2012-3-24 12:24 编辑
frjwdcyd 发表于 2012-3-24 12:20 static/image/common/back.gif
能帮忙做个简单的例子吗,新手
“先判断最低得那个0 然后把其他位都设置成固定的数字”这个貌似有点 ...
首先你要吧输入的数据的处理下把它处理成只有1个0的数据(比如 输入 11011011你要处理成 1111011)其他的数据都是1然后再用上面的程序判断输出就不会有毛刺了。 kebaojun305 发表于 2012-3-24 12:23 static/image/common/back.gif
首先你要吧输入的数据的处理下把它处理成只有1个0的数据(比如 输入 11011011你要处理成 1111011) ...
多谢!
我试试。
不能在一个CPLD中处理完所有逻辑吗?不想再改当前的电路了:L huatong 发表于 2012-3-24 12:23 static/image/common/back.gif
很奇怪啊,我这里看不出有毛刺啊.
按我回复的红色字体的方法试试。看看有没有毛刺 本帖最后由 kebaojun305 于 2012-3-24 12:30 编辑
frjwdcyd 发表于 2012-3-24 12:27 static/image/common/back.gif
多谢!
我试试。
不能在一个CPLD中处理完所有逻辑吗?不想再改当前的电路了...
就是在CPLD中完成啊。要不你还想加数字电路了:L 那么你用CPLD干么呢。:L 本帖最后由 kebaojun305 于 2012-3-24 12:48 编辑
frjwdcyd 发表于 2012-3-24 12:27 static/image/common/back.gif
多谢!
我试试。
不能在一个CPLD中处理完所有逻辑吗?不想再改当前的电路了...
你按我回复的红色字体部分仿真下 应该是能仿真到毛刺的。 主要是思路出问题了拿单片机的顺序执行来套CPLD的并行执行。 kebaojun305 发表于 2012-3-24 12:31 static/image/common/back.gif
你按我回复的红色字体部分仿真下 应该是能仿真到毛刺的。 主要是思路出问题了拿单片机的顺序执行来套 ...
的确是单片机顺序执行的思路:L。感觉很简单的逻辑用CPLD实现似乎很复杂!:L
”要保证输入的数据只有1个0“这句大概明白了,是防止因为延时else不能起作用的。
“应该加个缓冲寄存器先判断最低得那个0”还请kebaojun305 说的再详细点!以前没搞过,看书觉得很简单,可实际一干不是这么回事!
frjwdcyd 发表于 2012-3-24 20:08 static/image/common/back.gif
的确是单片机顺序执行的思路:L。感觉很简单的逻辑用CPLD实现似乎很复杂!:L
”要保证输入的数据只有1个0 ...
实际上你这个if else的语句在CPLD中 基本上每一个判断 是同时进行的(只是有个布线的延时而已,而且输出也是 如果输入有几个零 那么对应的有几个0的输出至于先后也是布线的延时 所以实际上输出是有冲突的 而且还很费电)而不是单片机的顺序执行。所以 结果出错了 我暂时想到的办法就是加驱动时钟用2个或以上的周期 来处理这个数据并输出结果 用组合逻辑 我还没有想到办法。 kebaojun305 发表于 2012-3-25 09:07 static/image/common/back.gif
实际上你这个if else的语句在CPLD中 基本上每一个判断 是同时进行的(只是有个布线的延时而已,而且输出 ...
能把大概的代码贴下吗?我水平的确{:sweat:} {:sweat:} {:sweat:} 因为输入信号的变换频率非常低,所以感觉应该一段时间后输出会稳定,但现象是一直输出脉冲。
所以我理解epm240每个时钟频率都读入、计算、输出。不知道我的理解对吗? 本帖最后由 kebaojun305 于 2012-3-25 10:18 编辑
如果输入频率变化很慢的就好处理了我刚试着写在调试中 思路就是 使用时钟信号驱动 把输入的21位并行数据转成21位的串行数据然后从第一位开始判断,如果是0 则退出(判断一次 计数器就加1) 则计数器中的数据就是 最前面0的位置然后根据这个位置 在用case选择输出就可以了。程序写了点在调试修改中。我也是刚开始学了快4个月,断断续续的。 frjwdcyd 发表于 2012-3-25 09:19 static/image/common/back.gif
因为输入信号的变换频率非常低,所以感觉应该一段时间后输出会稳定,但现象是一直输出脉冲。
所以我理解epm ...
至于是不是每个时钟都在输入 计算和输出要看你的设计 如果你的设计中敏感列表中有时钟信号 或者和时钟相关联的计算结果信号那么 你的理解是对的 否则则是错的。 本帖最后由 kebaojun305 于 2012-3-25 13:30 编辑
module help(wr,clk,in,out,rst,test,test1);
input clk,rst,wr;
input in;
output out;
reg out;
// test port
output test;
wire test;
assign test=bit_count;
output test1;
wire test1;
assign test1=bit_det_start;
//test portend
reg bit_count;
reg bit_det_start;//
reg in_buff;//
reg r0,r1;
always@(posedge clk or negedge rst)
begin
if(!rst) begin
r0<=1'b0;
r1<=1'b0;
end
else
begin
r0<=wr;
r1<=r0;
end
end
wire bit_start;
assignbit_start=(~r1)&r0;
reg bit_val;
always@(posedge clk or negedge rst )
begin
if(!rst) begin
bit_count<=5'b00000;
bit_det_start=1'b0;
end
else
begin
if(bit_det_start)
begin
in_buff=in_buff>>1;
in_buff<=1'b0;
if(in_buff)
bit_count<=bit_count+1'b1;
else
begin
bit_det_start=1'b0;
end
end
else
begin
if(bit_start) begin
bit_det_start<=1'b1;
bit_count<=5'b00000;
in_buff<=in;
end
end
end
end
always @(negedge bit_det_start or negedge rst)
begin
if(!rst)
out<=21'b000000000000000000000;
else
case(bit_count)
5'd0:out<=21'b111111111111111111100;
5'd1:out<=21'b111111111111111111001;
5'd2:out<=21'b111111111111111110011;
5'd3:out<=21'b111111111111111100111;
5'd4:out<=21'b111111111111111001111;
5'd5:out<=21'b111111111111110011111;
5'd6:out<=21'b111111111111100111111;
5'd7:out<=21'b111111111111001111111;
5'd8:out<=21'b111111111110011111111;
5'd9:out<=21'b111111111100111111111;
5'd10: out<=21'b111111111001111111111;
5'd11: out<=21'b111111110011111111111;
5'd12: out<=21'b111111100111111111111;
5'd13: out<=21'b111111001111111111111;
5'd14: out<=21'b111110011111111111111;//没有写完
default:;
endcase
end
endmodule调了大约3个小时终于调试好了已经仿真通过 现附上 源程序和工程文档 工程文档是 quartus 11.1 sp1 仿真软件 ModelSim-Altera 10.0c
后面2个端口是测试端口test和test1 wr是输入信号的锁存信号 上升沿信号锁存clk是处理时钟 in是21位数据输入out是21位数据输出,rst是复位信号,解码时间最长要22个时钟周期。
本帖最后由 linjpxt 于 2012-3-25 23:50 编辑
module encoder
(
input wire clk,
input wire indata,
input wire bj,
output wire outdata
);
reg data_reg;
always @ (posedge clk) //如果不加入时钟就写成 always @ (*)
begin
// x and z values are don't-care's
casex({bj,indata})
22'b1_xxxx_xxxx_xxxx_xxxx_xxxx_x: data_reg <= indata;
22'b0_xxxx_xxxx_xxxx_xxxx_xxxx_0: data_reg <= 21'b111111111111111111100;
22'b0_xxxx_xxxx_xxxx_xxxx_xxx0_1: data_reg <= 21'b111111111111111111001;
22'b0_xxxx_xxxx_xxxx_xxxx_xx01_1: data_reg <= 21'b111111111111111110011;
22'b0_xxxx_xxxx_xxxx_xxxx_x011_1: data_reg <= 21'b111111111111111100111;
22'b0_xxxx_xxxx_xxxx_xxxx_0111_1: data_reg <= 21'b111111111111111001111;
22'b0_xxxx_xxxx_xxxx_xxx0_1111_1: data_reg <= 21'b111111111111110011111;
22'b0_xxxx_xxxx_xxxx_xx01_1111_1: data_reg <= 21'b111111111111100111111;
22'b0_xxxx_xxxx_xxxx_x011_1111_1: data_reg <= 21'b111111111111001111111;
22'b0_xxxx_xxxx_xxxx_0111_1111_1: data_reg <= 21'b111111111110011111111;
22'b0_xxxx_xxxx_xxx0_1111_1111_1: data_reg <= 21'b111111111100111111111;
22'b0_xxxx_xxxx_xx01_1111_1111_1: data_reg <= 21'b111111111001111111111;
22'b0_xxxx_xxxx_x011_1111_1111_1: data_reg <= 21'b111111110011111111111;
22'b0_xxxx_xxxx_0111_1111_1111_1: data_reg <= 21'b111111100111111111111;
22'b0_xxxx_xxx0_1111_1111_1111_1: data_reg <= 21'b111111001111111111111;
22'b0_xxxx_xx01_1111_1111_1111_1: data_reg <= 21'b111110011111111111111;
22'b0_xxxx_x011_1111_1111_1111_1: data_reg <= 21'b111100111111111111111;
22'b0_xxxx_0111_1111_1111_1111_1: data_reg <= 21'b111001111111111111111;
22'b0_xxx0_1111_1111_1111_1111_1: data_reg <= 21'b110011111111111111111;
22'b0_xx01_1111_1111_1111_1111_1: data_reg <= 21'b100111111111111111111;
22'b0_x011_1111_1111_1111_1111_1: data_reg <= 21'b001111111111111111111;
22'b0_0111_1111_1111_1111_1111_1: data_reg <= 21'b011111111111111111111;
22'b0_1111_1111_1111_1111_1111_1: data_reg <= 21'b111111111111111111111;
endcase
end
// Catch the outgoing bit
assign outdata = data_reg;
endmodule kebaojun305 发表于 2012-3-25 12:36 static/image/common/back.gif
调了大约3个小时终于调试好了已经仿真通过 现附上 源程序和工程文档 工程文档是 quartus 11.1 sp1...
非常感谢!!{:handshake:} 我马上试一下!!! 你如果要用 估计还的在我源程序上更改下 那个启动信号估计你要从新处理下了 这年头学校里教的都是verilog不是VHDL了吗? 如果资源够用的话,查表是个不错的办法:
做一个21位地址,21位数据的RAM,数据输入作为地址,数据输出你要的结果,
XXXXXXXXXXXXXXXXXXX01 输出111111111111111111001
将地址满足XXXXXXXXXXXXXXXXXXX01条件的数据全部初始化为:111111111111111111001就可以了。 lanliang714 发表于 2012-3-28 09:15 static/image/common/back.gif
如果资源够用的话,查表是个不错的办法:
做一个21位地址,21位数据的RAM,数据输入作为地址,数据输出你要 ...
这本来就是一个查表的过程,只是先要对输入进行译码,这是属于优先译码器. 如果仅用时序控制,实际并不能完全解决1楼问题。
个人项目经验处理过类似问题:当CPLD时钟快,过信号变化慢,状态转换过程会有跳变,需要滤除。简单方法是,循环检测从低位起,时钟上升延,当检测到第1个0,再连续读n个值(n根据实际情况选定),如果在n个周期读到预设的m个0(比如n=10,m=8),判定有效值0,编码输出,否则,连续k个1(比如k=2),状态机检测高1个bit值判定。再周而复始。
选值结合实际用途,看似速度慢了,但输出相对稳定可靠。
页:
[1]