HDLBits(16)4.19

1|03 电路

1|13.2 时序逻辑

1|03.2.2 计数器

  •  Count1to10(Decade counter again)

与上题一样,区别是复位为1

module top_module( input clk, input reset, output [3:0] q); always @(posedge clk) begin if(reset) q <= 4'b0001; //复位为1 else if(q <= 4'b1001) q <= q + 1'b1; else q <= 4'b0001; end endmodule
  •  Coutslow(Slow decade couter)

一个0-9,同步复位且复位为0的计数器,但计数器不随clk变化而递增,而是由slowena使能信号控制

module top_module ( input clk, input slowena, input reset, output [3:0] q); always @ (posedge clk) begin if(reset) q <= 4'b0; else if(slowena == 1'b1) begin if(q == 4'd9) q <= 4'b0; else q <= q + 4'd1; end end endmodule
  •  Counter 1-12

 根据以下输入输出信号设计一个计算1~12的计数器

Reset:同步复位信号,高复位,将计数器复位为1.

Enable:使能信号高有效

Clk:时钟上升沿触发计数器工作

Q[3:0]:计数器输出

c_enable, c_load, c_d[3:0]:题目中给我们提供了一个4-bit的计数器,这三个信号是用于该4-bit计数器的控制信号。

题目提供给我们4-bit计数器

  1. 有enable信号,带复位和置位的计数器,将该计数器例化至我们的代码中。
  2. 再用一些其他的逻辑门来完成本题
module top_module ( input clk, input reset, input enable, output [3:0]Q, output c_enable, output c_load, output [3:0]c_d ); reg [3:0] temp; //4-bit 计数器的控制信号 assign c_enable = enable; assign c_load = reset | (Q == 4'd12 & enable == 1'b1); assign c_d = 4'b1; count4 the_counter (clk,c_enable,c_load,c_d,Q); endmodule
  •  Counter1000

OneHertz: 从1000Hz中分离出1Hz的信号;这个信号主要用作于数字时钟中。

利用一个模10的BCD计数器和尽量少的逻辑门建立一个时钟分频器。同时输出每个BCD计算器的使能信号(c_enable[0]为高位,c_enable[2]为低位)

module bcdcount ( input clk, input reset, output OneHertz, output [2:0] c_enable ); wire [3:0] q0,q1,q2; //1000 -> 100(q2) -> 10(q1) -> 1(q0) assign c_enable = {q1==4'd9 && q0==4'd9,q0==4'd9,1'b1}; assign OneHertz = {q2==4'd9 && q1==4'd9 && q0==4'd9}; bcdcount counter0 (clk, reset, c_enable[0], q0); bcdcount counter1 (clk, reset, c_enable[1], q1); bcdcount counter2 (clk, reset, c_enable[2], q2); endmodule
  • Countbcd(4-digit decimal counter)

设计一个4位BCD计数器。每个十进制数字使用4-bit来表示:q[3:0]是个位,q[4:7]是十位等,ena[3:1]表示个位、十位、百位的进位

module top_module ( input clk, input reset, output [3:1] ena, outout [15:0] q ); //分别实例化个十百千四个计数器子模块 //one count Inst1_count ( .clk(clk), .reset(reset), .ena(1'b1), .q(q[3:0]) ); //ten count Inst2_count ( .clk(clk), .reset(reset), .ena(q[3:0] == 4'd9), .q(q[7:4]) ); //hundred count Inst3_count ( .clk(clk), .reset(reset), .ena(q[7:4] == 4'd9 && q[3:0] == 4'd9), .q(q[11:8]) ); //thousand count Inst4_count ( .clk(clk), .reset(reset), .ena(q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9), .q(q[15:12]) ); assign ena = {q[11:8] == 4'd9 && q[7:4] == 4'd9 && q[3:0] == 4'd9 , q[7:4] == 4'd9 && q[3:0] == 4'd9 , q[3:0] == 4'd9} endmodule module count ( input clk, input reset, input ena, output reg[3:0] q ); always @ (posedge clk) begin if(reset) q <= 4'b0; else if (ena) begin if(q == 4'd9) q <= 4'd0; else q <= q+1'b1; end end endmodule
//不用子模块的方法,但此方法用到求余(%),实际FPGA中应避免使用除法和求余,因为需要使用很多资源 module top_module ( input clk, input reset, // Synchronous active-high reset output [3:1] ena, output [15:0] q ); assign ena = { q[11:8]==4'd9 && q[7:4]==4'd9 && q[3:0]==4'd9, q[7:4]==4'd9 && q[3:0]==4'd9, q[3:0]==4'd9 }; always @(posedge clk) if(reset) q <= 16'b0; else begin q[3:0] <= (q[3:0] + 1) % 10; if(ena[1]) q[7:4] <= (q[7:4] + 1) % 10; if(ena[2]) q[11:8] <= (q[11:8] + 1) % 10; if(ena[3]) q[15:12] <= (q[15:12] + 1) % 10; end endmodule
  •  Count clock

用计数器设计一个带AM/PM的12小时时钟。该计数器通过一个CLK进行计时,用ena使能信号来驱动时钟的递增。

reset信号将时钟复位为12:00 AM。 信号pm为0代表AM,为1代表PM。hh、mm和ss由数两个BCD计器构成hours(01~12), minutes(00~59) , second(00~59)。Reset信号比enable信号有更高的优先级,即使没有enable信号也可以进行复位操作。

Hint:需要注意的是从11:59:59 PM 到12:00:00 AM和从12:59:59 PM到01:00:00 PM的变化。

module top_module ( input clk, input reset, input ena, output pm, output [7:0] hh, output [7:0] mm, output [7:0] ss ); reg p; //0 is am, 1 is pm reg [7:0] h; reg [7:0] m; reg [7:0] s; always @ (posedge clk) begin if(reset) //reset to 12:00:00 AM begin p <= 0; h <= 8'h12; //为什么采用16进制? m <= 8'h00; s <= 8'h00; end else begin if(ena) begin if(s < 8'h59) begin if(s[3:0] < 4'h9) //s[3:0] is ones digit begin s[3:0] <= s[3:0] + 1'h1; end else begin s[3:0] <= 0; //59->00 s[7:4] <= s[7:4] + 1'h1; //tens digit end end else begin s <= 0; //s清零 if(m < 8'h59) //m同理s begin if(m[3:0] < 4'h9) begin m[3:0] <= m[3:0] + 1'h1; end else begin m[3:0] <= 0; m[7:4] <= m[7:4] + 1'h1; end end else begin m <= 1'h0; if(h == 8'h11) //AM / PM 转换 p = !p; if(h < 8'h12) begin if(h[3:0] < 4'h9) h[3:0] <= h[3:0] + 1'h1; else begin h[3:0] <= 4'h0; h[7:4] <= h[7:4] + 1'h1; end end else begin //hour 12 -> 1 h <= 1'h1; end end end end end end assign pm = p; assign hh = h; assign mm = m; assign ss = s; endmodule

1|03.2.3 移位寄存器

  • Shift4(4-bit shift register)

设计一个4bit异步复位,拥有同步置位和使能的右移移位寄存器

areset : 寄存器复位为0

load : 将data[3:0]输入至移位寄存器中

ena : 使能信号控制向右移动(q[3]q[2]q[1]q[0] ---> 0q[3]q[2]q[1],q[0]在移动后消失了,原先q[3]的位置变为0)

q : 移位寄存器中的数据

如果ena和load同时为高,load有更高的优先级。

module top_module( input clk, input areset, input load, input ena, input [3:0] data, output reg [3:0] q ); always @ (posedge clk or posedge areset) begin if(areset) q <= 4'b0; else if (load) q <= data; else if (ena) begin q[3:0] <= {1'b0,q[3:1]}; end end endmodule

 


__EOF__

本文作者LhTian
本文链接https://www.cnblogs.com/LhTian/p/17331092.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   LhTian21  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示