【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 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 <= {1'b0,q[3:1]};
	end
	else begin
		q <= q;
	end
end

endmodule

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) begin
	if (load) begin
		q <= data;
	end
	else begin
		case(ena)
			2'b01: q <= {q[0],q[99:1]};
			2'b10: q <= {q[98:0],q[99]};
			default: q <= q;
		endcase
	end
end

endmodule

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) begin
	if (load) begin
		q <= data;
	end
	else if (ena) begin
		case(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]};
		endcase
	end
end

endmodule

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'h1
    output [4:0]  q
); 

always @(posedge clk) begin
	if (reset) begin
		q <= 5'h1;
	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

endmodule

Mt2015 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;
endmodule

Lfsr32

构建一个 32 位 LFSR,在位位置 32、22、2 和 1 处使用抽头。 

module top_module(
    input          clk,
    input          reset,    // Active-high synchronous reset to 32'h1
    output [31:0]  q
); 

always @(posedge clk) begin
	if (reset) begin
		q <= 32'h1;
	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

endmodule

Shift 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

endmodule

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)  	
	);

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

endmodule

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) begin
 	if (enable) begin
 		FF <= {FF[6:0],S};
 	end
 	else begin
 		FF <= FF;
 	end
 end 

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) begin
	if (load) begin
		q <= data;
	end
	else begin
        q <= (~{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
end

endmodule

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)begin
        if (load) begin
        	q <= data;
        end
        else begin
            for(i=0;i<256;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 (i>0 && i<15) begin
                    count = q[239+i]+q[240+i]+q[241+i]+q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17];
                end
                else if (i>240 && i<255) begin
                    count = q[i-17]+q[i-16]+q[i-15]+q[i-1]+q[i+1]+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[i+15]+q[i+1]+q[i+31]+q[i+16]+q[i+17];
                end
                else if (i%16 == 15) begin
                    count = q[i-17]+q[i-16]+q[i-31]+q[i-1]+q[i-15]+q[i+15]+q[i+16]+q[i+1];
                end
                else begin
                    count = q[i-17]+q[i-16]+q[i-15]+q[i-1]+q[i+1]+q[i+15]+q[i+16]+q[i+17];
                end
                case(count)
                    4'd2:q[i] <= q[i];
                    4'd3:q[i] <= 1'b1;
                    default:q[i] <= 1'b0;
                endcase
            end
        end
    end

endmodule

Conwaylife

有一个一维的单元格数组(打开或关闭)。在每个时间步长中,每个单元的下一个状态是该单元的两个当前邻居的 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 <= {1'b0,q[511:1]} ^ {q[510:0],1'b0};
	end
end

endmodule
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 尼尔森(Nilsson)是一个常见的瑞典姓氏,源自瑞典北部和南部地区。它起源于北欧文化中的尼尔家族,被认为是一个古老而充满历史的姓氏。 尼尔森这个姓氏在瑞典历史上非常常见,许多著名的瑞典人都拥有这个姓氏,如瑞典足球传奇运动员弗雷迪·尼尔森(Freddy Nilsson)和知名作曲家利特罗尔·尼尔森(Litorol Nilsson)。 尼尔森这个姓氏在其他国家也很常见,尤其是在瑞典人移民的国家,如美国、加拿大、澳大利亚等。在这些国家,许多姓氏为Nilsson的人注重传承瑞典文化和家族价值观,保持着对祖先的敬意。 总的来说,尼尔森是一个具有瑞典瑞典文化和历史背景的常见姓氏,代表着家族和传统的重要价值。尼尔森家族在各个领域都有杰出的人物,他们的成就为尼尔森这个姓氏增添了光彩,同时也让人们对这个姓氏有了更多的认识。 ### 回答2: 尼尔森(Nillson)是一个常见的瑞典姓氏,也可以是一个人名。作为一个姓氏,它在瑞典和其他北欧国家非常常见。像其他姓氏一样,尼尔森在使用中可能有不同的拼写和变体。 作为一个人名,尼尔森通常指的是一个男性,尤其是在北欧国家。 尼尔森可能是一个家族姓氏,也可能是给予某人的名字。尼尔森是一个非常常见的名字,特别在瑞典和丹麦。 尼尔森这个名字的起源可以追溯到瑞典和丹麦的传统和文化。 在瑞典,尼尔森很可能是尼尔的儿子或后代的意思。在丹麦,尼尔森可能是尼尔的儿子后代的意思。 虽然尼尔森可能是一个普通的名字,但它并没有特定的象征意义。 它只是一个家族姓氏或被给予的名字,没有传递特定的信息或意义,而是代表某个人或家族的身份。 就像其他姓氏和名字一样,尼尔森的使用是为了代码某个人或家族的身份和传统。 ### 回答3: 尼尔森(Nilsson),一般指的是瑞典流行巨星哈里·尼尔森(Harry Nilsson)。 哈里·尼尔森是20世纪60年代和70年代最富盛名的瑞典流行歌手之一。他以其独特的嗓音和多才多艺的音乐才能而闻名,他的音乐作品涵盖了多种风格,包括摇滚、流行、乡村和爵士等。他的代表作品包括《Without You》、《Everybody's Talkin'》和《Coconut》等。 尼尔森以其独特的音域和深情的演唱风格而受到广泛赞誉。他擅长创作动情的歌曲,并通过他的音乐传达了许多情感和体验。他的歌曲经常描绘人们在爱情、友谊和人生各个方面的复杂情感,深受听众喜爱。 尼尔森的音乐成就令人瞩目,他的专辑《Nilsson Schmilsson》获得了格莱美奖,并获得了多次金唱片认证。他的音乐影响了许多后来的音乐人,包括披头士乐队的成员以及其他许多著名艺人。 尼尔森在音乐创作方面的突出才能与他的问题生活和不幸的命运并存。他的生活中充满了酗酒、药物滥用和人际关系问题,这些困扰最终对他的音乐事业产生了重大影响。尽管他在这些问题上经历了艰难的时期,但他的音乐天赋和创造力使他成为一个不可忽视的艺人。 总的来说,哈里·尼尔森是一个备受尊敬的艺术家,他以他独特的音乐才能和感人的歌曲在乐坛中留下了难以磨灭的印记。尽管他的一生经历了许多挑战和困难,但他的音乐将继续让我们回忆和怀念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linest-5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值