【HDLBits 刷题 8】Circuits(4)Sequential Logic---Shifts Registers More Circuits

【HDLBits 刷题 8】Circuits(4)Sequential Logic---Shifts Registers  More Circuits 目录写在前面Shifts RegistersShift4Rotate100Shift18Lfsr5Mt2015 lfsrLfsr32Shift registierShift registier23 input LUTMore CircuitsRule90Rule110Conwaylife写在前面本篇博客对 Circuits 部分的组合逻辑前两节做答案和部分解析一些比较简单的题目就直接给出答案有些难度再稍作讲解每道题的答案不一定唯一可以有多种解决方案欢迎共同讨论。Shifts RegistersShift4构建一个 4 位移位寄存器右移位具有异步复位、同步负载和使能功能。areset将移位寄存器重置为零。load加载带有数据的移位寄存器[30]而不是移位。ena向右移位q[3] 变为零q[0] 移出并消失。q移位寄存器的内容。如果 load 和 ena 输入都置位则 load 输入具有更高的优先级。module top_module( input clk, input areset, // async active-high reset to zero input load, input ena, input [3:0] data, output reg [3:0] q ); always (posedge clk or posedge areset) begin if (areset) begin q d0; end else if (load) begin q data; end else if (ena) begin q {1b0,q[3:1]}; end else begin q q; end end endmoduleRotate100构建一个 100 位左/右旋转器具有同步负载和左/右使能。旋转器从寄存器的另一端移入移出位这与丢弃移出位并移位为零的移位不同。如果启用旋转器将旋转位并不会修改/丢弃。load加载带有数据的移位寄存器[990]而不是旋转。ena[10]选择是否旋转以及旋转方向。2b01 向右旋转一位2b10 向左旋转一位2b00 和 2b11 不旋转。q旋转器的内容物。module top_module( input clk, input load, input [1:0] ena, input [99:0] data, output reg [99:0] q ); always (posedge clk) begin if (load) begin q data; end else begin case(ena) 2b01: q {q[0],q[99:1]}; 2b10: q {q[98:0],q[99]}; default: q q; endcase end end endmoduleShift18构建一个具有同步负载的 64 位算术移位寄存器。移位器可以向左和向右移动也可以按数量选择1位或8位位置。算术右移位在移位寄存器中数字的符号位在本例中为q[63]移位而不是像逻辑右移那样为零。考虑算术右移的另一种方法是它假设被移位的数字是有符号的并保留符号因此算术右移将有符号除以有符号数的2次幂。逻辑左移和算术左移之间没有区别。.load加载带有数据的移位寄存器[630]而不是移位。.ena选择是否移动。.amount选取要移动的方向和量。2b00向左移动 1 位。2b01向左移动 8 位。2b10向右移动 1 位。2b11向右移动 8 位。.q变速器的内容。module top_module( input clk, input load, input ena, input [1:0] amount, input [63:0] data, output reg [63:0] q ); always (posedge clk) begin if (load) begin q data; end else if (ena) begin case(amount) 2b00 : q {q[62:0],1b0}; 2b01 : q {q[55:0],8b0}; 2b10 : q {q[63],q[63:1]}; 2b11 : q {{8{q[63]}},q[63:8]}; endcase end end endmoduleLfsr5线性反馈移位寄存器是一种移位寄存器通常具有几个XOR门以产生移位寄存器的下一个状态。伽罗瓦LFSR是一种特殊的排列方式其中带有“抽头”的位位置与输出位进行XOR运算以产生其下一个值而位位置没有分路器移位。如果仔细选择丝锥位置则可以使LFSR达到“最大长度”。n 位的最大长度 LFSR 循环通过 2n重复前为 -1 个状态永远不会达到全零状态。下图显示了一个 5 位最大长度伽罗瓦 LFSR在位位置 5 和 3 处具有抽头。点击位置通常从 1 开始编号。请注意为了保持一致性我在位置 5 绘制了 XOR 门但其中一个 XOR 门输入为 0。module top_module( input clk, input reset, // Active-high synchronous reset to 5h1 output [4:0] q ); always (posedge clk) begin if (reset) begin q 5h1; end else begin q[4] q[0]; q[3] q[4]; q[2] q[3] ^ q[0]; q[1] q[2]; q[0] q[1]; end end endmoduleMt2015 lfsr为此时序电路编写 Verilog 代码子模块是可以的但顶层必须命名为 top_module。假设您要在DE1-SoC板上实现电路。将 R 输入连接到软件开关将时钟连接到 KEY[0]将 L 连接到 KEY[1]。将 Q 输出连接到红灯 LEDR。module top_module ( input [2:0] SW, // R input [1:0] KEY, // L and clk output [2:0] LEDR // Q ); wire [2:0] R; wire L; wire clk; reg [2:0] Q; assign R SW; assign clk KEY[0]; assign L KEY[1]; always (posedge clk) begin if (L) begin Q[0] R[0]; end else begin Q[0] Q[2]; end end always (posedge clk) begin if (L) begin Q[1] R[1]; end else begin Q[1] Q[0]; end end always (posedge clk) begin if (L) begin Q[2] R[2]; end else begin Q[2] Q[1] ^ Q[2]; end end assign LEDR Q; endmoduleLfsr32构建一个 32 位 LFSR在位位置 32、22、2 和 1 处使用抽头。module top_module( input clk, input reset, // Active-high synchronous reset to 32h1 output [31:0] q ); always (posedge clk) begin if (reset) begin q 32h1; end else begin q[31] q[0]; q[30] q[31]; q[29] q[30]; q[28] q[29]; q[27] q[28]; q[26] q[27]; q[25] q[26]; q[24] q[25]; q[23] q[24]; q[22] q[23]; q[21] q[22] ^ q[0]; q[20] q[21]; q[19] q[20]; q[18] q[19]; q[17] q[18]; q[16] q[17]; q[15] q[16]; q[14] q[15]; q[13] q[14]; q[12] q[13]; q[11] q[12]; q[10] q[11]; q[9] q[10]; q[8] q[9]; q[7] q[8]; q[6] q[7]; q[5] q[6]; q[4] q[5]; q[3] q[4]; q[2] q[3]; q[1] q[2] ^ q[0]; q[0] q[1] ^ q[0]; end end endmoduleShift registier实现移位寄存器module top_module ( input clk, input resetn, // synchronous reset input in, output out ); reg out1,out2,out3; always (posedge clk) begin if (!resetn) begin out1 d0; out2 d0; out3 d0; out d0; end else begin out1 in; out2 out1; out3 out2; out out3; end end endmoduleShift registier2为移位寄存器编写一个顶层 Verilog 模块top_module假设 n 4。在顶层模块中实例化 MUXDFF 子模块。R to SWclk to KEY[0]E to KEY[1]L to KEY[2]w to KEY[3]Q to LEDR[30]module top_module ( input [3:0] SW, input [3:0] KEY, output [3:0] LEDR ); MUXDFF MUXDFF_inst( .R(SW), .clk(KEY[0]), .E(KEY[1]), .L(KEY[2]), .w(KEY[3]), .Q(LEDR) ); endmodule module MUXDFF ( input [3:0] R, input clk, input E, input L, input w, output reg [3:0] Q ); always (posedge clk) begin if (E) begin if (L) begin Q[3] R[3]; end else begin Q[3] w; end end else if (!E) begin if (L) begin Q[3] R[3]; end else begin Q[3] Q[3]; end end end always (posedge clk) begin if (E) begin if (L) begin Q[2] R[2]; end else begin Q[2] Q[3]; end end else if (!E) begin if (L) begin Q[2] R[2]; end else begin Q[2] Q[2]; end end end always (posedge clk) begin if (E) begin if (L) begin Q[1] R[1]; end else begin Q[1] Q[2]; end end else if (!E) begin if (L) begin Q[1] R[1]; end else begin Q[1] Q[1]; end end end always (posedge clk) begin if (E) begin if (L) begin Q[0] R[0]; end else begin Q[0] Q[1]; end end else if (!E) begin if (L) begin Q[0] R[0]; end else begin Q[0] Q[0]; end end end endmodule3 input LUT在这个问题中将为8x1存储器设计一个电路其中写入存储器是通过移位来完成的并且读取是“随机访问”就像在典型的RAM中一样。然后将使用该电路实现3输入逻辑功能。首先创建一个具有8个D型触发器的8位移位寄存器。将触发器输出标记为 Q[0]...问题[7]移位寄存器输入应称为S它为Q[0]的输入供电MSB首先移位。启用输入控制是否移动。然后扩展电路以具有3个额外的输入ABC和一个输出Z。电路的行为应如下所示当ABC为000时ZQ[0]当ABC为001时ZQ[1]依此类推。电路应仅包含8位移位寄存器和多路复用器。题外话该电路称为3输入查找表LUT。module top_module ( input clk, input enable, input S, input A, B, C, output Z ); reg [7:0] FF; always (posedge clk) begin if (enable) begin FF {FF[6:0],S}; end else begin FF FF; end end assign Z FF[{A,B,C}]; endmoduleMore CircuitsRule90有一个一维的单元格数组打开或关闭。在每个时间步长中每个单元格的状态都会发生变化。在规则110中每个单元格的下一个状态仅取决于其自身及其两个相邻的数据module top_module( input clk, input load, input [511:0] data, output [511:0] q ); always (posedge clk) begin if (load) begin q data; end else begin q (~{1b0,q[511:1]} q) | (q ~{q[510:0],1b0}) | {~{1b0,q[511:1]} {q[510:0],1b0}} | {~q {q[510:0],1b0}}; end end endmoduleRule110Conway的Game of Life是一个二维元胞自动机。“游戏”在二维细胞网格上进行其中每个细胞要么是1活的要么是0死的。在每个时间步长中每个单元都会根据它有多少个邻数而改变状态0-1 邻数单元格变为 0。2 个邻数单元格状态不会更改。3 个邻数单元格变为 1。4 个以上的邻数单元格变为 0。在本电路中将使用16x16网格。为了使事情更有趣我们将使用16x16环形线圈其中两侧环绕到网格的另一侧。例如角单元格 00 有 8 个相邻项151、150、1515、01、015、11、10 和 11516x16 网格由长度为 256 的向量表示其中每行 16 个单元格由一个子向量表示q[150] 为行 0q[3116] 为第 1 行依此类推。load在下一个时钟边沿将数据加载到q中用于加载初始状态。q游戏的 16x16 当前状态每时钟周期更新一次。游戏状态应在每个时钟周期前进一个时间步长。有点类似扫雷游戏判定周围的炸弹这道题就是判断相应的位周围有多少个1把位的周围的数全部加起来就是1的个数。module top_module( input clk, input load, input [255:0] data, output [255:0] q ); reg [3:0] count; integer i; always (posedge clk)begin if (load) begin q data; end else begin for(i0;i256;i)begin if (i 0) begin count q[255] q[240] q[241] q[15] q[1] q[31] q[16] q[17]; end else if (i 15)begin count q[254] q[255] q[240] q[14] q[0] q[30] q[31] q[16]; end else if (i 240) begin count q[239] q[224] q[225] q[255] q[241] q[15] q[0] q[1]; end else if (i 255) begin count q[238] q[239] q[224] q[254] q[240] q[15] q[0] q[14]; end else if (i0 i15) begin count q[239i]q[240i]q[241i]q[i-1]q[i1]q[i15]q[i16]q[i17]; end else if (i240 i255) begin count q[i-17]q[i-16]q[i-15]q[i-1]q[i1]q[i-239]q[i-240]q[i-241]; end else if (i%16 0) begin count q[i-1]q[i-16]q[i-15]q[i15]q[i1]q[i31]q[i16]q[i17]; end else if (i%16 15) begin count q[i-17]q[i-16]q[i-31]q[i-1]q[i-15]q[i15]q[i16]q[i1]; end else begin count q[i-17]q[i-16]q[i-15]q[i-1]q[i1]q[i15]q[i16]q[i17]; end case(count) 4d2:q[i] q[i]; 4d3:q[i] 1b1; default:q[i] 1b0; endcase end end end endmoduleConwaylife有一个一维的单元格数组打开或关闭。在每个时间步长中每个单元的下一个状态是该单元的两个当前邻居的 XOR。表示此规则的更详细方式如下表所示其中单元格的下一个状态是自身及其两个相邻的函数。module top_module( input clk, input load, input [511:0] data, output [511:0] q ); integer i; always (posedge clk) begin if (load) begin q data; end else begin q {1b0,q[511:1]} ^ {q[510:0],1b0}; end end endmodule