【HDLBits 刷题 7】Circuits(3)Sequential Logic---Counters

2023-10-07 22:30

本文主要是介绍【HDLBits 刷题 7】Circuits(3)Sequential Logic---Counters,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

写在前面

Counters

Count15

Count10

Countslow

Counter1-12

Counter1000

Countbcd

Count clock

总结


写在前面

本篇博客对 Circuits 部分的组合逻辑前两节做答案和部分解析,一些比较简单的题目就直接给出答案,有些难度再稍作讲解,每道题的答案不一定唯一,可以有多种解决方案,欢迎共同讨论。

Counters

Count15

生成一个4位二进制计数器,其计数范围为0到15(包括0和15),周期为16。复位输入是同步的,应将计数器复位为0。

ee357787a6214fa2b556c32461af43c6.png

module top_module (input         clk,input         reset,      output [3:0]  q
);always @(posedge clk) beginif (reset) beginq <= 'd0;endelse beginq <= q + 'd1;end
endendmodule

Count10

构建一个计数从 0 到 9(包括 0 和 9)的计数器,周期为 10。复位输入是同步的,应将计数器复位为0。

b8ba431b51a84022b352b22f114cd426.png

module top_module (input         clk,input         reset,  output [3:0]  q
);always @(posedge clk) beginif (reset) beginq <= 'd0;endelse if (q == 'd9) beginq <= 'd0;		endelse beginq <= q + 'd1;end
end
endmodule

 Count1to10

制作一个计数为 1 到 10(包括 1)的计数器。复位输入是同步的,应将计数器复位为1。

d952feee087f4cde8e39acb352923c7b.png

module top_module (input         clk,input         reset,  output [3:0]  q
);always @(posedge clk) beginif (reset) beginq <= 'd1;endelse if (q == 'd10) beginq <= 'd1;		endelse beginq <= q + 'd1;end
end
endmodule

Countslow

构建一个计数从 0 到 9(包括 0 和 9)的计数器,周期为 10。复位输入是同步的,应将计数器复位为0。我们希望能够暂停计数器,而不是总是在每个时钟周期递增,因此 slowena 输入指示计数器何时应该递增。

8a4a39c3b7b044fd8cf16f06dcc5471f.png

module top_module (input         clk,input         slowena,input         reset,output [3:0]  q
);
always @(posedge clk) beginif (reset) beginq <= 'd0;endelse if (q == 'd9 && slowena) beginq <= 'd0;		endelse if (q < 'd9 && slowena) beginq <= q + 'd1;end
endendmodule

Counter1-12

设计具有以下输入和输出的 1-12 计数器:
重置同步高电平有效复位,强制计数器达到1
   .使设置高,使计数器运行
   .时钟正边沿触发时钟输入
   .问[3:0]计数器的输出
   .c_enable、c_load c_d[3:0]控制信号进入提供的4位计数器,因此可以验证正确的操作。

module top_module (input        clk,input        reset,input        enable,output [3:0] Q,output       c_enable,output       c_load,output [3:0] c_d
); assign c_enable = enable;assign c_load = reset | ((Q == 4'd12) && (enable == 1'b1));assign c_d = c_load ? 4'd1 : 4'd0;count4 the_counter (clk, c_enable, c_load, c_d , Q);endmodule

Counter1000

从 1000 Hz 时钟导出一个 1 Hz 信号,称为 OneHertz,可用于驱动一组小时/分/秒计数器的 Enable 信号,以创建数字挂钟。由于我们希望时钟每秒计数一次,因此必须每秒断言一个周期的OneHertz信号。使用模-10 (BCD) 计数器和尽可能少的其他门构建分频器。同时输出来自您使用的每个BCD计数器的使能信号(最快的计数器c_enable[0],最慢的计数器c_enable[2])。为您提供了以下 BCD 计数器。启用必须为高电平才能运行计数器。复位是同步的,设置为高电平以强制计数器归零。电路中的所有计数器必须直接使用相同的 1000 Hz 信号。

module top_module (input         clk,input         reset,output        OneHertz,output [2:0]  c_enable
);wire  [3:0]    a,b,c;
assign c_enable = {b=='d9 && a=='d9,a=='d9,1'b1};
assign OneHertz = a=='d9 && b=='d9 && c=='d9;bcdcount counter0 (clk, reset, c_enable[0], a);
bcdcount counter1 (clk, reset, c_enable[1], b);
bcdcount counter2 (clk, reset, c_enable[2], c);
endmodule

Countbcd

生成 4 位 BCD(二进制编码十进制)计数器。每个十进制数字使用4位编码:q[3:0]是1位数字,q[7:4]是十位数字,依此类推。对于数字 [3:1],还要输出一个使能信号,指示何时应递增上述三位数字中的每一位。

ebbad8c625544a4ba7975ffdf108bdde.png

module top_module (input          clk,input          reset,output [3:1]   ena,output [15:0]  q
);
reg  [3:0]  one,ten,hundred,thousand;//one
always @(posedge clk) beginif (reset) beginone <= 'd0;	endelse if (one == 'd9) beginone <= 'd0;endelse beginone <= one + 'd1;	end
end//ten
always @(posedge clk) beginif (reset) beginten <= 'd0;endelse if (ten == 'd9 && one == 'd9) beginten <= 'd0;endelse if (ena[1]) beginten <= ten + 'd1;endelse beginten <= ten;end
end//hundred
always @(posedge clk) beginif (reset) beginhundred <= 'd0;endelse if (hundred == 'd9 && ten == 'd9 && one == 'd9) beginhundred <= 'd0;endelse if (ena[2]) beginhundred <= hundred + 'd1;endelse beginhundred <= hundred;end
end//thousand
always @(posedge clk) beginif (reset) beginthousand <= 'd0;endelse if (thousand =='d9 && hundred == 'd9 && ten == 'd9 && one == 'd9) beginthousand <= 'd0;endelse if (ena[3]) beginthousand <= thousand + 'd1;endelse beginthousand <= thousand;end
end//ena[1] ena[2] ena[3]
assign ena[1] = (one=='d9);
assign ena[2] = (ten=='d9 && one=='d9);
assign ena[3] = (hundred=='d9 && ten=='d9 && one=='d9);//q
assign q = {thousand, hundred, ten, one};endmodule

Count clock

创建一组适合用作 12 小时制的计数器(带有 am/pm 指示器)。计数器由快速运行的 clk 计时,只要您的时钟递增(即每秒一次),就会有一个脉冲。重置将时钟重置为 12:00 AM。pm 对于 AM为 0,对于 PM 为 1。hh、mm 和 ss 是两个 BCD(二进制编码十进制)数字,分别表示小时(01-12)、分钟 (00-59)和秒(00-59)。重置的优先级高于启用,即使未启用,也可能发生重置。以下时序图显示了从11:59:59 AM到12:00:00 PM的翻转行为以及同步重置和启用行为。

677498816f1343d6b86766e74d1340fd.png

这里需要注意一点,就是小时、分钟、秒钟的个位十位都需要用十进制数表示,不能直接用十六进制表示,这是这道题的难点所在。 

module top_module(input         clk,input         reset,input         ena,output        pm,output [7:0]  hh,output [7:0]  mm,output [7:0]  ss
); reg         pm_temp;         //pm值寄存reg [3:0]   ss_ones;         //ss个位部分reg [3:0]   ss_tens;         //ss十位部分   reg [3:0]   mm_ones;         //mm个位部分   reg [3:0]   mm_tens;         //mm十位部分reg [3:0]   hh_ones;         //hh个位部分reg [3:0]   hh_tens;         //hh十位部分wire		add_ss_ones;     //ss个位计数开始信号wire		end_ss_ones;     //ss个位计数结束信号wire		add_ss_tens;     //ss十位计数开始信号wire		end_ss_tens;     //ss十位计数结束信号wire		add_mm_ones;     //mm个位计数开始信号wire		end_mm_ones;     //mm个位计数结束信号wire		add_mm_tens;     //mm十位计数开始信号wire		end_mm_tens;     //mm十位计数结束信号wire		add_hh_ones;     //hh个位计数开始信号wire		end_hh_ones_0;   //hh个位计数结束信号(十位为0)wire		end_hh_ones_1;   //hh个位计数结束信号(十位为1)wire		add_hh_tens;     //hh十位计数开始信号 wire		end_hh_tens_0;   //hh十位计数置0标志信号wire		end_hh_tens_1;   //hh十位计数置1标志信号wire		pm_ding;         //pm翻转标志信号assign add_ss_ones = ena;
assign end_ss_ones = add_ss_ones && (ss_ones == 4'd9);
always @(posedge clk)beginif(reset)beginss_ones <= 4'b0;endelse if(add_ss_ones)beginif(end_ss_ones)beginss_ones <= 4'b0;endelse beginss_ones <= ss_ones + 4'b1;endend
endassign add_ss_tens = end_ss_ones;
assign end_ss_tens = add_ss_tens && (ss_tens == 4'd5);
always @(posedge clk)beginif(reset)beginss_tens <= 4'b0;endelse if(add_ss_tens)beginif(end_ss_tens)beginss_tens <= 4'b0;endelse beginss_tens <= ss_tens + 4'b1;endend
endassign add_mm_ones = end_ss_tens;
assign end_mm_ones = add_mm_ones && (mm_ones == 4'd9);
always @(posedge clk)beginif(reset)beginmm_ones <= 4'b0;endelse if(add_mm_ones)beginif(end_mm_ones)beginmm_ones <= 4'b0;endelse beginmm_ones <= mm_ones + 4'b1;endend
endassign add_mm_tens = end_mm_ones;
assign end_mm_tens = add_mm_tens && (mm_tens == 4'd5);always @(posedge clk)beginif(reset)beginmm_tens <= 4'b0;endelse if(add_mm_tens)beginif(end_mm_tens)beginmm_tens <= 4'b0;endelse beginmm_tens <= mm_tens + 4'b1;endend
endassign add_hh_ones = end_mm_tens;
assign end_hh_ones_0 = add_hh_ones && (hh_ones == 4'd9);
assign end_hh_ones_1 = add_hh_ones && ((hh_ones == 4'd2) && (hh_tens == 4'd1));
always @(posedge clk)beginif(reset)beginhh_ones <= 4'd2;endelse if(add_hh_ones)beginif(end_hh_ones_0)beginhh_ones <= 4'b0;endelse if(end_hh_ones_1)beginhh_ones <= 4'b1;endelse beginhh_ones <= hh_ones+4'b1;endend
endassign add_hh_tens = end_mm_tens;
assign end_hh_tens_0 = add_hh_tens && end_hh_ones_1;
assign end_hh_tens_1 = add_hh_tens && end_hh_ones_0;
always @(posedge clk)beginif(reset)beginhh_tens <= 4'b1;endelse if(add_hh_tens)beginif(end_hh_tens_0)beginhh_tens <= 4'b0;endelse if(end_hh_tens_1)beginhh_tens <= hh_tens + 4'b1;endend
endalways@(posedge clk)beginif(reset)beginpm_temp <= 1'b0;endelse if(pm_ding)beginpm_temp <= ~pm_temp;end
endassign pm_ding = hh_tens == 4'd1 && hh_ones == 4'd1 && end_mm_tens;assign ss = {ss_tens, ss_ones};
assign mm = {mm_tens, mm_ones};
assign hh = {hh_tens, hh_ones};
assign pm = pm_temp;endmodule

总结

这部分主要学习计数器的使用,这个在实际设计中用的非常多,尤其是在处理数据的时候,计数器设计不难,但是需要注意计数值到边缘时的处理,是否有延时等情况。 

 

这篇关于【HDLBits 刷题 7】Circuits(3)Sequential Logic---Counters的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/160850

相关文章

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

hot100刷题第1-9题,三个专题哈希,双指针,滑动窗口

求满足条件的子数组,一般是前缀和、滑动窗口,经常结合哈希表; 区间操作元素,一般是前缀和、差分数组 数组有序,更大概率会用到二分搜索 目前已经掌握一些基本套路,重零刷起leetcode hot 100, 套路题按套路来,非套路题适当参考gpt解法。 一、梦开始的地方, 两数之和 class Solution:#注意要返回的是数组下标def twoSum(self, nums: Lis

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II 1.题目 1.1递增子序列 题目链接:491. 非递减子序列 - 力扣(LeetCode) 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0491.%E9%80%92%E

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II

代码随想录刷题day24丨93.复原IP地址 ,78.子集 , 90.子集II 1.题目 1.1复原IP地址 题目链接:93. 复原 IP 地址 - 力扣(LeetCode) 视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0093.%E5%A4%8

【笔记】数据结构刷题09

快速排序 215. 数组中的第K个最大元素 class Solution {public:int findKthLargest(vector<int>& nums, int k) {return divide(nums,0,nums.size()-1,nums.size()-k);}int divide(vector<int>& nums,int left,int right,int k)

C语言:刷题日志(1)

一.阶乘计算升级版 本题要求实现一个打印非负整数阶乘的函数。 其中n是用户传入的参数,其值不超过1000。如果n是非负整数,则该函数必须在一行中打印出n!的值,否则打印“Invalid input”。 首先,知道阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。那么我们先来个简单的阶乘计算吧。 #include<stdio.h>int Fact(int n){if (n <=

【每日刷题】Day112

【每日刷题】Day112 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 1137. 第 N 个泰波那契数 - 力扣(LeetCode) 2. 面试题 08.01. 三步问题 - 力扣(LeetCode) 3. LCR 088. 使用最小花费爬楼梯 - 力扣(LeetCode) 1. 1137. 第 N 个泰波那契数 - 力扣(LeetCo

【数据结构】【java】leetcode刷题记录--链表

简介 链表是一种常见的基础数据结构,它由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。在Java中,链表通常用于实现动态数据结构,因为它可以根据需要动态地增加或减少节点。 链表简介: 节点结构:链表中的每个元素称为节点(Node),每个节点包含两部分:数据域(存储数据)和指针域(存储下一个节点的地址)动态性:链表的长度不是固定的,可以根据需要动态地增减节点。内存分配:链表中的节点

代码随想录 刷题记录-28 图论 (5)最短路径

一、dijkstra(朴素版)精讲 47. 参加科学大会 思路 本题就是求最短路,最短路是图论中的经典问题即:给出一个有向图,一个起点,一个终点,问起点到终点的最短路径。 接下来讲解最短路算法中的 dijkstra 算法。 dijkstra算法:在有权图(权值非负数)中求从起点到其他节点的最短路径算法。 需要注意两点: dijkstra 算法可以同时求 起点到所有节点的最短路径权值不

【Hot100算法刷题集】哈希-01-两数之和(暴力枚举再优化,也不是哈希表的对手)

🏠关于专栏:专栏用于记录LeetCode中Hot100专题的所有题目 🎯每日努力一点点,技术变化看得见 题目转载 题目描述 🔒link->题目跳转链接 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那 两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任