本文主要是介绍【HDLBits 刷题 8】Circuits(4)Sequential Logic---Shifts Registers More Circuits,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
写在前面
Shifts Registers
Shift4
Rotate100
Shift18
Lfsr5
Mt2015 lfsr
Lfsr32
Shift registier
Shift registier2
3 input LUT
More Circuits
Rule90
Rule110
Conwaylife
写在前面
本篇博客对 Circuits 部分的组合逻辑前两节做答案和部分解析,一些比较简单的题目就直接给出答案,有些难度再稍作讲解,每道题的答案不一定唯一,可以有多种解决方案,欢迎共同讨论。
Shifts Registers
Shift4
构建一个 4 位移位寄存器(右移位),具有异步复位、同步负载和使能功能。
- areset:将移位寄存器重置为零。
- load:加载带有数据的移位寄存器[3:0]而不是移位。
- ena:向右移位(q[3] 变为零,q[0] 移出并消失)。
- q:移位寄存器的内容。
如果 load 和 ena 输入都置位,则 load 输入具有更高的优先级。
module top_module(input clk,input areset, // async active-high reset to zeroinput load,input ena,input [3:0] data,output reg [3:0] q
); always @(posedge clk or posedge areset) beginif (areset) beginq <= 'd0;endelse if (load) beginq <= data;endelse if (ena) beginq <= {1'b0,q[3:1]};endelse beginq <= q;end
endendmodule
Rotate100
构建一个 100 位左/右旋转器,具有同步负载和左/右使能。旋转器从寄存器的另一端移入移出位,这与丢弃移出位并移位为零的移位不同。如果启用旋转器将旋转位,并不会修改/丢弃。
- load:加载带有数据的移位寄存器[99:0]而不是旋转。
- ena[1:0]:选择是否旋转以及旋转方向。
- 2'b01 向右旋转一位
- 2'b10 向左旋转一位
- 2'b00 和 2'b11 不旋转。
- q:旋转器的内容物。
module top_module(input clk,input load,input [1:0] ena,input [99:0] data,output reg [99:0] q
);
always @(posedge clk) beginif (load) beginq <= data;endelse begincase(ena)2'b01: q <= {q[0],q[99:1]};2'b10: q <= {q[98:0],q[99]};default: q <= q;endcaseend
endendmodule
Shift18
构建一个具有同步负载的 64 位算术移位寄存器。移位器可以向左和向右移动,也可以按数量选择1位或8位位置。算术右移位在移位寄存器中数字的符号位(在本例中为q[63])移位,而不是像逻辑右移那样为零。考虑算术右移的另一种方法是,它假设被移位的数字是有符号的并保留符号,因此算术右移将有符号除以有符号数的2次幂。
逻辑左移和算术左移之间没有区别。
- .load:加载带有数据的移位寄存器[63:0]而不是移位。
- .ena:选择是否移动。
- .amount:选取要移动的方向和量。
- 2'b00:向左移动 1 位。
- 2'b01:向左移动 8 位。
- 2'b10:向右移动 1 位。
- 2'b11:向右移动 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) beginif (load) beginq <= data;endelse if (ena) begincase(amount)2'b00 : q <= {q[62:0],1'b0};2'b01 : q <= {q[55:0],8'b0};2'b10 : q <= {q[63],q[63:1]};2'b11 : q <= {{8{q[63]}},q[63:8]};endcaseend
endendmodule
Lfsr5
线性反馈移位寄存器是一种移位寄存器,通常具有几个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 5'h1output [4:0] q
); always @(posedge clk) beginif (reset) beginq <= 5'h1;endelse beginq[4] <= q[0];q[3] <= q[4];q[2] <= q[3] ^ q[0];q[1] <= q[2];q[0] <= q[1];end
endendmodule
Mt2015 lfsr
为此时序电路编写 Verilog 代码(子模块是可以的,但顶层必须命名为 top_module)。假设您要在DE1-SoC板上实现电路。将 R 输入连接到软件开关,将时钟连接到 KEY[0],将 L 连接到 KEY[1]。将 Q 输出连接到红灯 LEDR。
module top_module (input [2:0] SW, // Rinput [1:0] KEY, // L and clkoutput [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) beginif (L) beginQ[0] <= R[0];endelse beginQ[0] <= Q[2];endend always @(posedge clk) beginif (L) beginQ[1] <= R[1];endelse beginQ[1] <= Q[0];endendalways @(posedge clk) beginif (L) beginQ[2] <= R[2];endelse beginQ[2] <= Q[1] ^ Q[2];endendassign LEDR = Q;
endmodule
Lfsr32
构建一个 32 位 LFSR,在位位置 32、22、2 和 1 处使用抽头。
module top_module(input clk,input reset, // Active-high synchronous reset to 32'h1output [31:0] q
); always @(posedge clk) beginif (reset) beginq <= 32'h1;endelse beginq[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
endendmodule
Shift registier
实现移位寄存器
module top_module (input clk,input resetn, // synchronous resetinput in,output out
);
reg out1,out2,out3;always @(posedge clk) beginif (!resetn) beginout1 <= 'd0;out2 <= 'd0;out3 <= 'd0;out <= 'd0;endelse beginout1 <= in;out2 <= out1;out3 <= out2;out <= out3;end
endendmodule
Shift registier2
为移位寄存器编写一个顶层 Verilog 模块(top_module)假设 n = 4。在顶层模块中实例化 MUXDFF 子模块。
- R to SW
- clk to KEY[0]
- E to KEY[1]
- L to KEY[2]
- w to KEY[3]
- Q to LEDR[3:0]
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) );endmodulemodule MUXDFF (input [3:0] R,input clk,input E,input L,input w,output reg [3:0] Q
);always @(posedge clk) beginif (E) beginif (L) beginQ[3] <= R[3];endelse beginQ[3] <= w;endendelse if (!E) beginif (L) beginQ[3] <= R[3];endelse beginQ[3] <= Q[3];endend
endalways @(posedge clk) beginif (E) beginif (L) beginQ[2] <= R[2];endelse beginQ[2] <= Q[3];endendelse if (!E) beginif (L) beginQ[2] <= R[2];endelse beginQ[2] <= Q[2];endend
endalways @(posedge clk) beginif (E) beginif (L) beginQ[1] <= R[1];endelse beginQ[1] <= Q[2];endendelse if (!E) beginif (L) beginQ[1] <= R[1];endelse beginQ[1] <= Q[1];endend
endalways @(posedge clk) beginif (E) beginif (L) beginQ[0] <= R[0];endelse beginQ[0] <= Q[1];endendelse if (!E) beginif (L) beginQ[0] <= R[0];endelse beginQ[0] <= Q[0];endend
endendmodule
3 input LUT
在这个问题中,将为8x1存储器设计一个电路,其中写入存储器是通过移位来完成的,并且读取是“随机访问”,就像在典型的RAM中一样。然后,将使用该电路实现3输入逻辑功能。首先,创建一个具有8个D型触发器的8位移位寄存器。将触发器输出标记为 Q[0]...问题[7]移位寄存器输入应称为S,它为Q[0]的输入供电(MSB首先移位)。启用输入控制是否移动。然后,扩展电路以具有3个额外的输入A,B,C和一个输出Z。电路的行为应如下所示:当ABC为000时,Z=Q[0],当ABC为
001时,Z=Q[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) beginif (enable) beginFF <= {FF[6:0],S};endelse beginFF <= FF;endend assign Z = FF[{A,B,C}];endmodule
More Circuits
Rule90
有一个一维的单元格数组(打开或关闭)。在每个时间步长中,每个单元格的状态都会发生变化。在规则110中,每个单元格的下一个状态仅取决于其自身及其两个相邻的数据:
module top_module(input clk,input load,input [511:0] data,output [511:0] q
);
always @(posedge clk) beginif (load) beginq <= data;endelse beginq <= (~{1'b0,q[511:1]} & q) | (q & ~{q[510:0],1'b0}) | {~{1'b0,q[511:1]} & {q[510:0],1'b0}} | {~q & {q[510:0],1'b0}};end
endendmodule
Rule110
Conway的Game of Life是一个二维元胞自动机。
“游戏”在二维细胞网格上进行,其中每个细胞要么是1(活的)要么是0(死的)。在每个时间步长中,每个单元都会根据它有多少个邻数而改变状态:
- 0-1 邻数:单元格变为 0。
- 2 个邻数:单元格状态不会更改。
- 3 个邻数:单元格变为 1。
- 4 个以上的邻数:单元格变为 0。
在本电路中,将使用16x16网格。为了使事情更有趣,我们将使用16x16环形线圈,其中两侧环绕到网格的另一侧。例如,角单元格 (0,0) 有 8 个相邻项:(15,1)、
(15,0)、(15,15)、(0,1)、(0,15)、(1,1)、(1,0) 和 (1,15)
16x16 网格由长度为 256 的向量表示,其中每行 16 个单元格由一个子向量表示:q[15:0] 为行 0,q[31:16] 为第 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)beginif (load) beginq <= data;endelse beginfor(i=0;i<256;i++)beginif (i == 0) begincount = q[255] + q[240] + q[241] + q[15] + q[1] + q[31] + q[16] + q[17];endelse if (i == 15)begincount = q[254] + q[255] + q[240] + q[14] + q[0] + q[30] + q[31] + q[16];endelse if (i == 240) begincount = q[239] + q[224] + q[225] + q[255] + q[241] + q[15] + q[0] + q[1];endelse if (i == 255) begincount = q[238] + q[239] + q[224] + q[254] + q[240] + q[15] + q[0] + q[14];endelse if (i>0 && i<15) begincount = q[239+i]+q[240+i]+q[241+i]+q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17];endelse if (i>240 && i<255) begincount = q[i-17]+q[i-16]+q[i-15]+q[i-1]+q[i+1]+q[i-239]+q[i-240]+q[i-241];endelse if (i%16 == 0) begincount = q[i-1]+q[i-16]+q[i-15]+q[i+15]+q[i+1]+q[i+31]+q[i+16]+q[i+17];endelse if (i%16 == 15) begincount = q[i-17]+q[i-16]+q[i-31]+q[i-1]+q[i-15]+q[i+15]+q[i+16]+q[i+1];endelse begincount = q[i-17]+q[i-16]+q[i-15]+q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17];endcase(count)4'd2:q[i] <= q[i];4'd3:q[i] <= 1'b1;default:q[i] <= 1'b0;endcaseendendendendmodule
Conwaylife
有一个一维的单元格数组(打开或关闭)。在每个时间步长中,每个单元的下一个状态是该单元的两个当前邻居的 XOR。表示此规则的更详细方式如下表所示,其中单元格的下一个状态是自身及其两个相邻的函数。
module top_module(input clk,input load,input [511:0] data,output [511:0] q
);integer i;
always @(posedge clk) beginif (load) beginq <= data;endelse beginq <= {1'b0,q[511:1]} ^ {q[510:0],1'b0};end
endendmodule
这篇关于【HDLBits 刷题 8】Circuits(4)Sequential Logic---Shifts Registers More Circuits的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!