• 【HDLBits 刷题 13】Circuits(8)Buliding Larger Circuits


    目录

    写在前面

    Buliding Larger Circuits

    count1k

    shiftcount

    fsm seq

    fsmshift

    fsm

    fancytimer

    fsm onehot


    写在前面

    以下的解题方法不一定为最佳解决方案,有更好的方法欢迎提出,共同学习,共同进步!

    Buliding Larger Circuits

    count1k

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

    1. module top_module (
    2. input clk,
    3. input reset,
    4. output [9:0] q
    5. );
    6. always @(posedge clk) begin
    7. if (reset) begin
    8. q <= 'd0;
    9. end
    10. else if (q=='d999) begin
    11. q <= 'd0;
    12. end
    13. else begin
    14. q <= q + 'd1;
    15. end
    16. end
    17. endmodule

    shiftcount

    这是一系列五个练习中的第一个组件,该练习从几个较小的电路中构建一个复杂的计数器。

    构建一个四位移位寄存器,该寄存器也可用作向下计数器。当shift_ena为 1 时,首先以最高有效位移位。当count_ena为1时,移位寄存器中的当前数字将递减。由于整个系统不使用shift_ena和count_ena,因此如果两个控制输入均为1,则电路的作用无关紧要(这主要意味着哪种情况获得更高的优先级并不重要)。

    1. module top_module (
    2. input clk,
    3. input shift_ena,
    4. input count_ena,
    5. input data,
    6. output [3:0] q
    7. );
    8. always @(posedge clk) begin
    9. if (shift_ena) begin
    10. q <= {q[2:0],data};
    11. end
    12. else if (count_ena) begin
    13. q <= q - 'd1;
    14. end
    15. else begin
    16. q <= q;
    17. end
    18. end
    19. endmodule

    fsm seq

    这是一系列五个练习中的第二个组件,该练习从几个较小的电路中构建一个复杂的计数器。

    构建一个在输入位流中搜索序列 1101 的有限状态机。找到序列后,应将 start_shifting 设置为 1,直到重置。陷入最终状态的目的是模拟在尚未实现的更大的FSM中进入其他状态。我们将在接下来的几个练习中扩展此 FSM。

    1. module top_module (
    2. input clk,
    3. input reset, // Synchronous reset
    4. input data,
    5. output start_shifting
    6. );
    7. //状态申明
    8. parameter IDLE = 'd1;
    9. parameter A_1 = 'd2;
    10. parameter B_1 = 'd3;
    11. parameter C_0 = 'd4;
    12. parameter D_1 = 'd5;
    13. //现态和次态
    14. reg [2:0] state;
    15. reg [2:0] next_state;
    16. //状态机第一段,状态初始化,时序逻辑非阻塞赋值
    17. always @(posedge clk) begin
    18. if (reset) begin
    19. state <= IDLE;
    20. end
    21. else begin
    22. state <= next_state;
    23. end
    24. end
    25. //状态机第二段,状态跳转,阻塞赋值
    26. always @(*) begin
    27. next_state = state;
    28. case(state)
    29. IDLE: begin
    30. if (data) begin
    31. next_state = A_1;
    32. end
    33. else begin
    34. next_state = IDLE;
    35. end
    36. end
    37. A_1: begin
    38. if (data) begin
    39. next_state = B_1;
    40. end
    41. else begin
    42. next_state = IDLE;
    43. end
    44. end
    45. B_1: begin
    46. if (~data) begin
    47. next_state = C_0;
    48. end
    49. else begin
    50. next_state = B_1;
    51. end
    52. end
    53. C_0: begin
    54. if (data) begin
    55. next_state = D_1;
    56. end
    57. else begin
    58. next_state = IDLE;
    59. end
    60. end
    61. D_1: begin
    62. next_state = D_1;
    63. end
    64. default: begin
    65. next_state = IDLE;
    66. end
    67. endcase
    68. end
    69. //状态机第三段,结果输出,组合逻辑
    70. assign start_shifting = (state==D_1);
    71. endmodule

    fsmshift

    这是一系列五个练习中的第三个组件,该练习从几个较小的电路中构建一个复杂的计数器。

    作为用于控制移位寄存器的FSM的一部分,我们希望能够在检测到正确的位模式时使移位寄存器精确4个时钟周期,考虑前面的处理序列检测,因此 FSM 的这一部分仅处理启用移位寄存器 4 个周期。

    每当FSM复位时,置位shift_ena 4个周期,然后永远为0(直到复位)。

    1. module top_module (
    2. input clk,
    3. input reset, // Synchronous reset
    4. output shift_ena
    5. );
    6. reg [1:0] cnt;
    7. always @(posedge clk) begin
    8. if (reset) begin
    9. cnt <= 'd0;
    10. end
    11. else begin
    12. cnt <= cnt + 'd1;
    13. end
    14. end
    15. always @(posedge clk) begin
    16. if (reset) begin
    17. shift_ena <= 'd1;
    18. end
    19. else if (cnt=='d3) begin
    20. shift_ena <= 'd0;
    21. end
    22. else begin
    23. shift_ena <= shift_ena;
    24. end
    25. end
    26. endmodule

    fsm

    这是一系列五个练习中的第四个组件,该练习从几个较小的电路中构建一个复杂的计数器。

    想要创建一个计时器,

    1. 在检测到特定模式 (1101) 时启动,
    2. 再移位 4 位,以确定延迟的持续时间,
    3. 等待计数器完成计数,以及
    4. 通知用户并等待用户确认计时器。

    在这个问题中,只实现控制计时器的有限状态机。此处不包括数据路径(计数器和某些比较器)。

    串行数据在数据输入引脚上可用。当接收到模式1101时,状态机必须断言输出shift_ena正好4个时钟周期。

    之后,状态机断言其计数输出以指示它正在等待计数器,并等待输入done_counting为高电平。

    此时,状态机必须断言 done 以通知用户计时器已超时,并等到输入 ack 为 1,然后重置以查找下一个匹配的开始序列 (1101)。

    状态机应重置为开始搜索输入序列1101的状态。

    下面是预期输入和输出的示例。“x”状态可能读起来有点混乱。它们表明,密克罗尼西亚联邦不应关心该周期中的特定输入信号。例如,一旦检测到 1101 模式,FSM 将不再查看数据输入,直到完成其他所有操作后恢复搜索。

    1. module top_module (
    2. input clk,
    3. input reset, // Synchronous reset
    4. input data,
    5. input ack,
    6. input done_counting,
    7. output shift_ena,
    8. output counting,
    9. output done
    10. );
    11. //状态申明
    12. parameter IDLE = 'd1;
    13. parameter A_1 = 'd2;
    14. parameter B_1 = 'd3;
    15. parameter C_0 = 'd4;
    16. parameter CNT_1 = 'd5;
    17. parameter CNT_2 = 'd6;
    18. parameter CNT_3 = 'd7;
    19. parameter CNT_4 = 'd8;
    20. parameter CNT = 'd9;
    21. parameter WAIT = 'd10;
    22. //现态和次态
    23. reg [3:0] state;
    24. reg [3:0] next_state;
    25. //状态机第一段,状态初始化,时序逻辑非阻塞赋值
    26. always @(posedge clk) begin
    27. if (reset) begin
    28. state <= IDLE;
    29. end
    30. else begin
    31. state <= next_state;
    32. end
    33. end
    34. //状态机第二段,状态跳转,阻塞赋值
    35. always @(*) begin
    36. next_state = state;
    37. case(state)
    38. IDLE: begin
    39. if (data) begin
    40. next_state = A_1;
    41. end
    42. else begin
    43. next_state = IDLE;
    44. end
    45. end
    46. A_1: begin
    47. if (data) begin
    48. next_state = B_1;
    49. end
    50. else begin
    51. next_state = IDLE;
    52. end
    53. end
    54. B_1: begin
    55. if (~data) begin
    56. next_state = C_0;
    57. end
    58. else begin
    59. next_state = B_1;
    60. end
    61. end
    62. C_0: begin
    63. if (data) begin
    64. next_state = CNT_1;
    65. end
    66. else begin
    67. next_state = IDLE;
    68. end
    69. end
    70. CNT_1: begin
    71. next_state = CNT_2;
    72. end
    73. CNT_2: begin
    74. next_state = CNT_3;
    75. end
    76. CNT_3: begin
    77. next_state = CNT_4;
    78. end
    79. CNT_4: begin
    80. next_state = CNT;
    81. end
    82. CNT: begin
    83. if (done_counting) begin
    84. next_state = WAIT;
    85. end
    86. else begin
    87. next_state = CNT;
    88. end
    89. end
    90. WAIT: begin
    91. if (ack) begin
    92. next_state = IDLE;
    93. end
    94. else begin
    95. next_state = WAIT;
    96. end
    97. end
    98. default: begin
    99. next_state = IDLE;
    100. end
    101. endcase
    102. end
    103. //状态机第三段,结果输出,组合逻辑
    104. assign shift_ena = (state==CNT_1) | (state==CNT_2) | (state==CNT_3) | (state==CNT_4);
    105. assign counting = state==CNT;
    106. assign done = state==WAIT;
    107. endmodule

    fancytimer

    这是一系列五个练习中的第五个组件,该练习从几个较小的电路中构建一个复杂的计数器。

    想要创建一个具有一个输入的计时器:

    1. 当检测到特定输入模式 (1101) 时启动,
    2. 再移位 4 位,以确定延迟的持续时间,
    3. 等待计数器完成计数,以及
    4. 通知用户并等待用户确认计时器。

    串行数据在数据输入引脚上可用。当接收到码型1101时,电路必须在接下来的4位中移位,最高有效位在先。这 4 位决定了定时器延迟的持续时间。我把它称为延迟[3:0]。

    之后,状态机断言其计数输出以指示它正在计数。状态机必须精确计数(延迟[3:0] + 1)* 1000个时钟周期。例如,delay=0 表示计数 1000 个周期,delay=5 表示计数 6000 个周期。同时输出当前剩余时间。这应该等于延迟 1000 个周期,然后延迟-1 表示 1000 个周期,依此类推,直到 0 表示 1000 个周期。当电路不计数时,计数[3:0]输出是“不在乎”(任何值都方便你实现)。

    此时,电路必须断言完成以通知用户计时器已超时,并等到输入ack为1,然后重置以查找下一个出现的开始序列(1101)。

    电路应复位到开始搜索输入序列1101的状态。

    下面是预期输入和输出的示例。“x”状态可能读起来有点混乱。它们表明,密克罗尼西亚联邦不应关心该周期中的特定输入信号。例如,一旦读取了1101和延迟[3:0],电路就不再查看数据输入,直到完成其他所有操作后恢复搜索。在本例中,电路计数为 2000 个时钟周期,因为延迟 [3:0] 值为 4'b0001。最后几个周期以延迟[3:0] = 4'b1110开始另一个计数,这将计数15000个周期。

    1. module top_module (
    2. input clk,
    3. input reset, // Synchronous reset
    4. input data,
    5. input ack,
    6. output [3:0] count,
    7. output counting,
    8. output done
    9. );
    10. //状态申明
    11. parameter IDLE = 'd1;
    12. parameter A_1 = 'd2;
    13. parameter B_1 = 'd3;
    14. parameter C_0 = 'd4;
    15. parameter SHIFT_1 = 'd5;
    16. parameter SHIFT_2 = 'd6;
    17. parameter SHIFT_3 = 'd7;
    18. parameter SHIFT_4 = 'd8;
    19. parameter CNT = 'd9;
    20. parameter WAIT = 'd10;
    21. //现态和次态
    22. reg [3:0] state;
    23. reg [3:0] next_state;
    24. reg [3:0] delay;
    25. reg [15:0] delay_cnt;
    26. reg [3:0] delay_num;
    27. wire delay_cnt_done;
    28. //当计数到设定的计数值时,将延时计数完成标志信号拉高
    29. assign delay_cnt_done = (delay_cnt == ((delay + 'd1) * 'd1000))?'d1:'d0;
    30. //状态机第一段,状态初始化,时序逻辑非阻塞赋值
    31. always @(posedge clk) begin
    32. if (reset) begin
    33. state <= IDLE;
    34. end
    35. else begin
    36. state <= next_state;
    37. end
    38. end
    39. //状态机第二段,状态跳转,阻塞赋值
    40. always @(*) begin
    41. next_state = state;
    42. case(state)
    43. IDLE: begin
    44. if (data) begin
    45. next_state = A_1;
    46. end
    47. else begin
    48. next_state = IDLE;
    49. end
    50. end
    51. A_1: begin
    52. if (data) begin
    53. next_state = B_1;
    54. end
    55. else begin
    56. next_state = IDLE;
    57. end
    58. end
    59. B_1: begin
    60. if (~data) begin
    61. next_state = C_0;
    62. end
    63. else begin
    64. next_state = B_1;
    65. end
    66. end
    67. C_0: begin
    68. if (data) begin
    69. next_state = SHIFT_1;
    70. end
    71. else begin
    72. next_state = IDLE;
    73. end
    74. end
    75. SHIFT_1: begin
    76. next_state = SHIFT_2;
    77. delay[3] = data;
    78. end
    79. SHIFT_2: begin
    80. next_state = SHIFT_3;
    81. delay[2] = data;
    82. end
    83. SHIFT_3: begin
    84. next_state = SHIFT_4;
    85. delay[1] = data;
    86. end
    87. SHIFT_4: begin
    88. next_state = CNT;
    89. delay[0] = data;
    90. end
    91. CNT: begin
    92. if (delay_cnt_done) begin
    93. next_state = WAIT;
    94. end
    95. else begin
    96. next_state = CNT;
    97. end
    98. end
    99. WAIT: begin
    100. if (ack) begin
    101. next_state = IDLE;
    102. end
    103. else begin
    104. next_state = WAIT;
    105. end
    106. end
    107. default: begin
    108. next_state = IDLE;
    109. end
    110. endcase
    111. end
    112. //delay_cnt
    113. always @(posedge clk) begin
    114. if (reset) begin
    115. delay_cnt <= 'd0;
    116. end
    117. else if (next_state == WAIT) begin
    118. delay_cnt <= 'd0;
    119. end
    120. else if (next_state == CNT) begin
    121. delay_cnt <= delay_cnt + 'd1;
    122. end
    123. else begin
    124. delay_cnt <= delay_cnt;
    125. end
    126. end
    127. //对于延时计数的范围值,确定具体的count值
    128. always @(*) begin
    129. if (delay_cnt <= 'd1000) begin
    130. delay_num = 'd0;
    131. end
    132. else if (delay_cnt > 'd1000 && delay_cnt <= 'd2000) begin
    133. delay_num = 'd1;
    134. end
    135. else if (delay_cnt > 'd2000 && delay_cnt <= 'd3000) begin
    136. delay_num = 'd2;
    137. end
    138. else if (delay_cnt > 'd3000 && delay_cnt <= 'd4000) begin
    139. delay_num = 'd3;
    140. end
    141. else if (delay_cnt > 'd4000 && delay_cnt <= 'd5000) begin
    142. delay_num = 'd4;
    143. end
    144. else if (delay_cnt > 'd5000 && delay_cnt <= 'd6000) begin
    145. delay_num = 'd5;
    146. end
    147. else if (delay_cnt > 'd6000 && delay_cnt <= 'd7000) begin
    148. delay_num = 'd6;
    149. end
    150. else if (delay_cnt > 'd7000 && delay_cnt <= 'd8000) begin
    151. delay_num = 'd7;
    152. end
    153. else if (delay_cnt > 'd8000 && delay_cnt <= 'd9000) begin
    154. delay_num = 'd8;
    155. end
    156. else if (delay_cnt > 'd9000 && delay_cnt <= 'd10000) begin
    157. delay_num = 'd9;
    158. end
    159. else if (delay_cnt > 'd10000 && delay_cnt <= 'd11000) begin
    160. delay_num = 'd10;
    161. end
    162. else if (delay_cnt > 'd11000 && delay_cnt <= 'd12000) begin
    163. delay_num = 'd11;
    164. end
    165. else if (delay_cnt > 'd12000 && delay_cnt <= 'd13000) begin
    166. delay_num = 'd12;
    167. end
    168. else if (delay_cnt > 'd13000 && delay_cnt <= 'd14000) begin
    169. delay_num = 'd13;
    170. end
    171. else if (delay_cnt > 'd14000 && delay_cnt <= 'd15000) begin
    172. delay_num = 'd14;
    173. end
    174. else if (delay_cnt > 'd15000 && delay_cnt <= 'd16000) begin
    175. delay_num = 'd15;
    176. end
    177. else begin
    178. delay_num = 'd0;
    179. end
    180. end
    181. //状态机第三段,结果输出,组合逻辑
    182. assign count = (state == CNT)?(delay - delay_num):'d0;
    183. assign counting = (state == CNT);
    184. assign done = (state == WAIT);
    185. endmodule

    fsm onehot

    假设使用以下单热编码,则通过检查派生下一状态逻辑方程和输出逻辑方程:(S,S1,S11,S110,B0,B1,B2,B3,计数,等待)= (10'b0000000001,10'b00000000010,10'b00000000100,...,10'b10000000000)

    1. module top_module(
    2. input d,
    3. input done_counting,
    4. input ack,
    5. input [9:0] state, // 10-bit one-hot current state
    6. output B3_next,
    7. output S_next,
    8. output S1_next,
    9. output Count_next,
    10. output Wait_next,
    11. output done,
    12. output counting,
    13. output shift_ena
    14. );
    15. parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
    16. assign B3_next = (state[B2]);
    17. assign S_next = (state[S] && ~d) | (state[S1] && ~d) | (state[S110] && ~d) | (state[Wait] && ack);
    18. assign S1_next = (state[S] && d);
    19. assign Count_next = (state[B3] | (state[Count] && ~done_counting));
    20. assign Wait_next = (state[Count] && done_counting) | (state[Wait] && ~ack);
    21. assign done = state[Wait];
    22. assign counting = state[Count];
    23. assign shift_ena = (state[B0] | state[B1] | state[B2] | state[B3]);
    24. endmodule
  • 相关阅读:
    [附源码]计算机毕业设计JAVA星期八酒店管理系统
    数据库系统原理与应用教程(059)—— MySQL 练习题:操作题 1-10(三)
    sentry安装self-hosted版,前端监控平台
    无法加载文件 C:\Users\haoqi\Documents\WindowsPowerShell\profile.ps1,因为在此系统上禁止运行脚本
    Android检测其他应用是否安装
    Java-SPI机制详解
    1.1 Mediapipe随手简记(一)
    RSS订阅微信公众号初探-feed43
    Java HashMap 详解
    怎么设计个性时尚的班服?一起来看看莱佛士学生的设计
  • 原文地址:https://blog.csdn.net/m0_61298445/article/details/126452630