概述
HLD Bits刷题记录
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、count clock
- 二、代码实现
- 第一次写的时候,忽略了十进制这个问题,下意识按照满59返回,导致最后答案是不对的。后面仔细看题目发现是用BCD计数器实现。
- 总结
前言
之前刷题都没有记录,从今天开始稍微记录一下,这个过程中遇到的一些问题,也是方便自己以后查看。
一、count clock
Create a set of counters suitable for use as a 12-hour clock (with am/pm indicator). Your counters are clocked by a fast-running clk, with a pulse on ena whenever your clock should increment (i.e., once per second).
reset resets the clock to 12:00 AM. pm is 0 for AM and 1 for PM. hh, mm, and ss are two BCD (Binary-Coded Decimal) digits each for hours (01-12), minutes (00-59), and seconds (00-59). Reset has higher priority than enable, and can occur even when not enabled.
The following timing diagram shows the rollover behaviour from 11:59:59 AM to 12:00:00 PM and the synchronous reset and enable behaviour.
题目意思很简单,实现一个时钟功能就行,同时用pm的高低区分上午和下午。
主要问题在于,要求使用二进制编码的十进制计数器实现。那计数器范围为0-9,计满9就得返回0.
二、代码实现
第一次写的时候,忽略了十进制这个问题,下意识按照满59返回,导致最后答案是不对的。后面仔细看题目发现是用BCD计数器实现。
代码如下:
```java
module top_module(
input clk,
input reset, //高电平复位(同步)
input ena, //1:计数;0:保持
output pm,
output [7:0] hh,//时针
output [7:0] mm,//分针
output [7:0] ss); //秒针
//用BCD计数器,最高到9,那就得把小时、分钟、秒钟都按照个位和十位来写
reg [3:0] s_1; //秒钟个位
reg [3:0] s_10; //秒钟十位
reg [3:0] m_1;
reg [3:0] m_10;
reg [3:0] h_1;
reg [3:0] h_10;
//计数器状态跳转
//秒钟
wire s_1_end;
assign s_1_end = ena && s_1==4'd9; //9s
always@(posedge clk)
begin
if(reset)
s_1 <= 4'd0;
else
s_1 <= ena ? (s_1_end ? 4'd0 : s_1+4'b1) : s_1;
end
//十位为5,个位为9,即59返回0.为了方便表示,可以新定义变量,所以十位不能超过5,要注意这一点
wire s_end;
assign s_end = s_1_end && s_10==4'd5; //59s
always@(posedge clk)
begin
if(reset)
s_10 <= 4'd0;
else
s_10 <= s_1_end ? (s_end ? 4'd0 : s_10+4'b1) : s_10;
end
//分钟的跳转,以秒钟为前提,满59秒分钟加一。
//同样,为了方便表示,再定义变量
wire m_1_end;
assign m_1_end = s_end && m_1==4'd9; //9分59秒
always@(posedge clk)
begin
if(reset)
m_1 <= 4'd0;
else
m_1 <= s_end ? (m_1_end ? 4'd0 : m_1+4'b1) : m_1;
end
wire m_10_end;
assign m_10_end = m_1_end && m_10==4'd5; //59分59秒
always@(posedge clk)
begin
if(reset)
m_10 <= 4'd0;
else //分针最大为5
m_10 <= m_1_end ? (m_10_end ? 4'd0 : m_10+4'b1) : m_10;
end
//时钟,分钟59为转变界限,但是要注意时针只有1-12。个位和十位数字有变化
wire h_1_end0;
assign h_1_end0 = m_10_end && h_1==4'd9; //09:59:59
wire h_1_end1;
assign h_1_end1 = m_10_end && h_10==4'd1 && h_1==4'd2; //12:59:59
always@(posedge clk)
begin
if(reset)
h_1 <= 4'd2; //注意,时针复位是复位到12点,个位为2
else
h_1 <= m_10_end ? (h_1_end0 ? 4'd0 : (h_1_end1 ? 4'd1 : h_1+4'b1)) : h_1;
end
wire h_10_end0;
assign h_10_end0 = m_10_end && h_1_end1;
wire h_10_end1;
assign h_10_end1 = m_10_end && h_1_end0;
always@(posedge clk)
begin
if(reset)
h_10 <= 4'd1;
else if(m_10_end)
begin
if(h_10_end0)
h_10 <= 4'd0;
else if(h_10_end1)
h_10 <= h_10+4'b1;
end
else
h_10 <= h_10;
end
reg p_m;
//11:59:59下一周期发生变化
wire pm_change;
assign pm_change = h_10==4'd1 && h_1==4'd1 && m_10_end;
always@(posedge clk)
begin
if(reset)
p_m <= 1'b0;
else
p_m <= pm_change ? ~p_m : p_m;
end
assign ss = {s_10,s_1};
assign mm = {m_10,m_1};
assign hh = {h_10,h_1};
assign pm = p_m;
endmodule
总结
以上就是对这个题的解答了,这个题是做到目前我错的次数最多的,所以记录一下,主要问题是使能信号没有加好,之前一直是11,22,33…的计数,来回检查,发现是使能的问题,没有做好保持,另外需要注意的就是在对指针进行定义的时候,和分针和秒针是不太一样的。
最后
以上就是如意长颈鹿为你收集整理的HDLBits刷题counter前言一、count clock二、代码实现总结的全部内容,希望文章能够帮你解决HDLBits刷题counter前言一、count clock二、代码实现总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复