HDLBits-count clock解题记录

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
	
    wire [3:0] i_en;
   // wire pm_temp;
   //assign pm_temp = (hh == {4'd1, 4'd1} && mm == {4'd5,4'd9} && ss == {4'd5, 4'd9}) ? (~pm) : pm;
   // assign pm = pm_temp;
    assign i_en = {mm[7:4] == 8'd5 && mm[3:0] == 8'd9 && ss[7:4] == 8'd5 && ss[3:0] == 8'd9,//i_en[3]
                   mm[3:0] == 8'd9 && ss[7:4] == 8'd5 && ss[3:0] == 8'd9,		//i_en[2]
                   ss[7:4] == 8'd5 && ss[3:0] == 8'd9,	//i_en[1]
                   ss[3:0] == 8'd9};					//i_en[0]
    
    bcd i0 (clk, reset, 	ena, 4'd0, 4'd9, ss[3:0]); 
    bcd i1 (clk, reset, i_en[0] & ena, 4'd0, 4'd5, ss[7:4]); 
       
    bcd i2 (clk, reset, i_en[1], 4'd0, 4'd9, mm[3:0]); 
    bcd i3 (clk, reset, i_en[2], 4'd0, 4'd5, mm[7:4]); 
    
    bcd_h1 i4 (clk, reset, i_en[3], hh[7:0]); 
    pm i5 (clk, reset, hh, mm, ss, pm); 
endmodule
//可选择范围的计数器;start表示计数起点,end表示计数终点
module bcd(
    input clk,
    input reset,
    input i_enable,
    input [3:0] starting,
    input [3:0] ending,
    output [3:0] num); 
   
    always @(posedge clk)
        begin
           if(reset) begin
                num <= starting;
           end
           else begin
               if(i_enable) begin
                    if(num == ending) begin
                        num <= starting;
                    end
                    else begin
                        num <= num + 1'b1;
                    end
               end
               else begin
                  num <= num;
               end
            end 
        end
endmodule
 //小时    
module bcd_h1(
    input clk,
    input reset,
    input i_enable,
    output [7:0] num); 
    reg [3:0] hours;
    
    always @(posedge clk)
        begin
           if(reset) begin
               num = {4'd1,4'd2};
               hours = 4'd12;
            end
            else begin
                if(i_enable) begin //i_enable_h1 = 1:表示十位数为1
                    if(hours == 4'd12) begin
                        num   = {4'd0,4'd1};
                        hours = 4'd1;
                    end
                    else begin
                        hours = hours + 1'b1;
                        num   = num + 1'b1;
                    end
                end
                else begin
                    hours = hours;
                    num   = num;
                end
                if(hours < 4'd10) begin
                    num = {4'd0, hours}; 
                end
                else begin
                    num = {4'd1, hours - 4'd10};
                end
            end 
        end
endmodule

module pm(
    input clk,
    input reset,
    input [7:0] hh,
    input [7:0] mm,
    input [7:0] ss,
    output pm); 
    
    always @(posedge clk)
        begin
           if(reset) begin
               pm <= 'b0;
            end
            else begin
                if(hh == {4'd1, 4'd1} && mm == {4'd5,4'd9} && ss == {4'd5, 4'd9}) begin 
                    pm <= ~pm;
                end
                else begin
                    pm <= pm;
                end
            end 
        end
endmodule

题目描述

设计一个带有am/pm指示的12小时时钟。当reset时时钟指向12:00am。pm为0时表示AM,pm为1表示PM。hh, mm, ss都是用连个BCD码表示hh(1-12),mm(0-59),ss(0-59)。reset的优先级高于enable信号。

当时钟在11:59:59am时下一刻在12:00:00PM

遇见问题1

若代码中出现此下情况

assign pm = {hh == 8'd11 && mm == 8'd59 && ss == 8'd59} ? ~pm : pm;

调试过程中便会出现如下错误:调试过程超出了限制次数5000次,一般的这种错误会出现在组合逻辑电路中(回环)。在组合逻辑电路中对敏感变量进行赋值,而敏感变量一变化,组合逻辑块就会进行赋值,赋值又会让敏感变量变化,如此循环,并且组合电路动作几乎不花时间,这便成了一个死循环。

# ** Error (suppressible): (vsim-3601) Iteration limit 5000 reached at time 15 ps.
This usually means your code is broken and the simulator can't simulate it. It's often caused by having a combinational loop or a latch with race conditions that oscillates, causing the simulator to never settle to a fixed value at this particular point in the simulation. Combinational loops can occur if some combinational logic (including always@(*) blocks) consumes a signal that it modifies. It can sometimes be caused by thinking in C while writing Verilog. Look for Quartus Warning (10240 or 13012) or Info (10041) regarding inferred latches or unsafe latch behaviour.

解决:利用电平铭感描述组合的逻辑块

module pm(
    input clk,
    input reset,
    input [7:0] hh,
    input [7:0] mm,
    input [7:0] ss,
    output pm); 
    
    always @(posedge clk)
        begin
           if(reset) begin
               pm <= 'b0;
            end
            else begin
                if(hh == {4'd1, 4'd1} && mm == {4'd5,4'd9} && ss == {4'd5, 4'd9}) begin 
                    pm <= ~pm;
                end
                else begin
                    pm <= pm;
                end
            end 
        end
endmodule

问题2

当我在小时hh的代码子模块中使用非阻塞赋值语句时出现了延迟现象

改图为延迟产生的时序仿真

 

该图未正确的仿真时序

 阻塞:语句的“右式计算”和“左式更新”完全完成之后,才开始下一条语句;

非阻塞:当前语句的执行不会阻塞下一语句的执行;begin-end语句块中的各个赋值语句时同步执行的。

        执行过程:1. 将非阻塞赋值放入调度队列中;

                           2. 仿真工具开始执行下一条语句而不等待当前语句执行完毕

                (先计算等式右边结果,并保存在事件队列中,等到时间调度时,将其赋值给左边)

赋值类型的选择取决于建模的逻辑类型。一般的:

        1. 时序逻辑电路中使用非阻塞赋值

                非阻塞赋值在块结束后完成赋值操作,次赋值方式可以避免在仿真出现冒险与竞争

        2. 组合逻辑电路中一般使用阻塞赋值

                阻塞赋值方式可以使变量的值在赋值语句执行完之后立刻改变

        3.  assign语句中必须使用阻塞赋值语句

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值