两个always块同时对一个reg类型变量赋值的问题
[复制链接]
两个always块同时对一个reg类型变量赋值的问题 问题描述: pps信号为秒脉冲信号(GPS授时模块中的同步秒脉冲),每个一秒钟给fpga发送一个信号,稳定精度为20ns左右,而且占空比可调(与该问题无关)。 一个rom 由m4k块产生,大小为8bit位宽,64words,即地址总线位宽为6位宽,事先存放好编辑好的数据。rom中的数为0-255,由8bit决定。 秒脉冲pps信号,连接到一个6位宽的计数器counter1,每来一个pps信号,计数器加一,作为rom的地址,同时,pps信号还作为rom的时钟信号,pps信号到来时,就可以在rom的输出端口得到存储在rom中某个单元的一个值,具体由来了多少个pps信号决定(因为pps决定地址选择)。 功能:秒脉冲pps到来,产生counter1,输出rom后,同时产生一个新的计数器counter2(自增计数器),将rom作为该计数器的脉冲计数个数,计数器counter2 计数单位为系统时钟 sys_clk;当计数器到达rom计数后,将输出信号output信号置1,持续500ns(或指定25个数个系统时钟)后,output信号置0,此时,1秒钟还没有到呢,才过去5500ns,等来下一个秒脉冲pps[i+1]到来,重复以上动作,直到第62个秒脉冲pps到来,后结束。 为什么 5500ns:系统时钟50mhz 即周期20ns。从收到秒脉冲pps时,到output信号置0,所经历的最长时间:计算如下: 假设,rom=255 则 rom*20ns = 5100ns 再加上output为1的持续时间500ns 共计 5500ns,即1秒钟还没到呢。 综合来讲要实现的功能为:每当秒脉冲pps信号到来,即启动计数器,计数的脉冲个数由rom中指定单元的数据给出,计数器到时后,fpga上某一引脚(记为output)输出为1,持续可设定的时间,如500ns。 这里output信号持续500ns 是否还有在重新生成一个计数器? 6位宽的计数器counter1,产生rom的地址 file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image002.jpg 制作rom,选择ROM-1-PORT file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image004.jpg 8Bits 64words file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image006.jpg 去掉‘q’output port file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image008.jpg 选择初始化数据,mif文件 file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image010.jpg launch.mif文件中的数据内容 file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image012.jpg rom_addr为计数器的输出值,图中所示,rom_addr也出现了不稳定的值,如16,计数器记到16之前,出现了毛刺。 file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image014.jpg 同样 在rom_value中也出现了一些不稳定的值 file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image016.jpg file:///C:/DOCUME~1/user/LOCALS~1/Temp/msohtml1/01/clip_image018.jpg 请问为什么会产生毛刺,如何消除毛刺,应该怎么实现上面的功能? module launch(sys_clk,rst_n,pps,rom_addr,rom_value,launch); input sys_clk; input rst_n; input pps; output rom_addr; output rom_value; output launch; reg launch; wire [5:0 ]rom_addr; wire [7:0 ]rom_value; counter_lpm counter_lpm_inst (.clock ( pps ),.q (rom_addr )); sys_rom sys_rom_inst (.address ( rom_addr ),.clock( pps ),.q ( rom_value )); reg cnt_flag; reg [7:0 ]cnt_value; always @(posedge pps) begin cnt_flag <= 1'b1; end reg [7:0]cnt; always @(posedge sys_clk or negedge rst_n) if (!rst_n) begin launch <= 1'b0;launch <= 1'b0; end else if (cnt_flag == 1'b1) begin if (cnt < rom_value) cnt<= cnt+1'b1; else begin cnt<=1'b0; launch <= 1'b1; cnt_flag <= 1'b0;end end else launch <= 1'b0; endmodule testbench 如下 `timescale 1 ns/ 1 ns module launch_vlg_tst(); reg pps; reg rst_n; reg sys_clk; // wires wire [5:0 ]rom_addr; wire [7:0 ]rom_value; // assign statements (if any) launch i1 (.sys_clk(sys_clk),.rst_n(rst_n),.pps(pps), .rom_addr(rom_addr),.rom_value(rom_value)); initial begin rst_n = 0; #100; rst_n = 1; #100000; $finish; end initial begin sys_clk = 0; forever #10 sys_clk = ~sys_clk; end initial begin pps = 0; #100; forever #300 pps = ~pps; end endmodule
|