刷完这套题,我才发现Verilog原来如此简单----HDLBits答案系列---- Shift register
给大家推荐一个非常好的练习Verilog的网站,有一两百道题,基本涵盖了Verilog语法的方方面面,是一个非常好的入门学习网站。网站连接:HDLBits
写在前面
全部答案汇总:刷完这套题,我才发现Verilog原来如此简单----HDLBits答案汇总
今天更新Circuits章节中Sequential Logic的1个小节:Shift register。
4-bit shift register
题目:
设计一个4-bit的移位寄存器(右移),带异步复位信号,同步载入信号和使能信号。
- areset: 异步复位信号,复位值为0
- load:有效时,寄存器载入data的值,而不是移位;load优先级高于ena
- ena: 右移使能信号
- q: 移位寄存器的内容
个人思路:
右移的移位寄存器:最高位取0,整体右移一位,最低位舍弃。load优先级高于移位ena。
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'd0;
else if(load)
q <= data;
else if(ena)
q <= q >> 1'b1; //右移一位
else
q <= q;
end
endmodule
Left/right rotator
题目:
构建一个100位的左右旋转器,同步load,左右旋转需使能。旋转器从另一端输入移位的位元,不像移位器那样丢弃移位的位元而以零位移位。如果启用,旋转器就会旋转这些位,而不会修改或丢弃它们。
- load:加载100位的移位寄存器数据
- ena[1:0]:2’b01 右转1bit; 2’b10 左转1bit;其他情况不转
- q:旋转器内容
个人思路:
本题与上题的区别在于,右移后最低位不舍弃,而是将其放到最高位上;右移后最高位不舍弃,而是将其放到最低位上。比较类似流水灯的效果。此外,设计到左移和右移的选择,所以就可以使用case语句做选择。
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)
q <= data;
else begin
case(ena)
2'b01: q <= {q[0],q[99:1]};
2'b10: q <= {q[98:0],q[99]};
default:;
endcase
end
end
endmodule
Left/right arithmetic shift by 1 or 8
题目:
建立一个64位的算术移位寄存器,同步加载。移位器可以左移和右移,并按1位或8位的位置,按数量选择。
算术右移将移位移位寄存器中数字(在本例中为q[63])的符号位,而不是逻辑右移所做的零。另一种考虑算术右移的方法是它假设被移的数是有符号的并保留符号,所以算术右移可以将一个有符号的数除以2的幂。逻辑左移和算术左移之间没有区别。
- load:加载数据
- ena:决定是否移位
- amount:决定移位方向与数量:2’b00:左移1位;2’b01:左移8位;2’b10:右移1位;2’b11:右移8位
- q:寄存器内容(输出)
个人思路:
逻辑移位:左移时,低位补0;右移时,高位补0。
算数移位:左移时,低位补0;算术右移符号位要一起移动,并且在左边补上符号位,也就是如果符号位是1就补1符号位是0就补0 。
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)
q <= data;
else begin
if(ena)
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]};
default:;
endcase
else
q <= q;
end
end
endmodule
5-bit LFSR
题目:
下图显示了一个5位最大长度的Galois LFSR,它在5和3位处进行了取样(抽头为3、5,抽头位置通常从1开始编号)。注意,为了一致性,我在5号位置画了异或门,但其中一个异或门输入是0。

个人思路:
关于LFSR可参考我的这篇博文:线性反馈移位寄存器LFSR
现在仅仅根据电路图给出解答。
module top_module(
input clk,
input reset, // Active-high synchronous reset to 5'h1
output [4:0] q
);
always @(posedge clk)begin
if(reset)
q <= 5'h1;
else begin
q[4] <= 1'b0 ^ q[0];
q[3] <= q[4];
q[2] <= q[3] ^ q[0];
q[1] <= q[2];
q[0] <= q[1];
end
end
endmodule
3-bit LFSR
题目:
为这个序列电路编写Verilog代码。假设你要在DE1-SoC板上实现这个电路。将R输入连接到SW开关,将时钟连接到key[0],将L连接到key[1],将Q输出连接到红灯LEDR上。

个人思路:
基本同上题一致,不同的是多了三个2选1模块,需要做下选择判断。
module top_module (
input [2:0] SW, // R
input [1:0] KEY, // L and clk
output [2:0] LEDR); // Q
always @(posedge KEY[0])begin
if(KEY[1])begin
LEDR[0] <= SW[0];
LEDR[1] <= SW[1];
LEDR[2] <= SW[2];
end
else begin
LEDR[0] <= LEDR[2];
LEDR[1] <= LEDR[0];
LEDR[2] <= LEDR[2] ^ LEDR[1];
end
end
endmodule
32-bit LFSR
题目:构建一个32位的Galois LFSR,其抽头位置为32、22、2和1。
个人思路:
抽头位置为32:q[31] <= 1'b0 ^ q[0]; 抽头位置为22、2、1 :q[21] <= q[22] ^ q[0],q[1] <= q[2] ^ q[0],q[0] <= q[1] ^ q[0];其他情况:q[i] <= q[i+1]; 其他情况比较多,一个个手写的话代码效率比较低,可以使用for语句或者generate-for语句,这样比较快,但是综合出来的电路规模会变大,消耗的逻辑资源会变多。
module top_module(
input clk,
input reset, // Active-high synchronous reset to 32'h1
output [31:0] q
);
integer i;
always @(posedge clk)begin
if(reset)
q <= 32'h1;
else begin
for(i=0;i<32;i=i+1)begin
if((i==21)||(i==1)||(i==0))
q[i] <= q[i+1] ^ q[0];
else if(i==31)
q[31] <= 1'b0 ^ q[0];
else
q[i] <= q[i+1];
end
end
end
endmodule
Shift register
题目:
实现如下电路。

个人思路:
可以看到,每个时钟周期,后一位的输入都来自前一位的输出,所以这是一个左移的移位寄存器(假设out为最高位)。
module top_module (
input clk,
input resetn, // synchronous reset
input in,
output out
);
reg [3:0] out_temp;
assign out = out_temp[3];
always @(posedge clk)begin
if(!resetn)
out_temp <= 4'b0;
else
out_temp <= {out_temp[2:0],in};
end
endmodule
Shift register
题目:
实现如下电路。
- Connect the R inputs to the SW switches,
- clk to KEY[0],
- E to KEY[1],
- L to KEY[2], and
- w to KEY[3].
- Connect the outputs to the red lights LEDR[3:0].

个人思路:
之前做过这个的子模块的题目,题目还把链接给出来了,例化这个子模块4次就行了。
module top_module (
input [3:0] SW,
input [3:0] KEY,
output [3:0] LEDR
);
MUXDFF inst1(
.clk (KEY[0]),
.w (KEY[3]),
.R (SW[3]),
.E (KEY[1]),
.L (KEY[2]),
.Q (LEDR[3])
);
MUXDFF inst2(
.clk (KEY[0]),
.w (LEDR[3]),
.R (SW[2]),
.E (KEY[1]),
.L (KEY[2]),
.Q (LEDR[2])
);
MUXDFF inst3(
.clk (KEY[0]),
.w (LEDR[2]),
.R (SW[1]),
.E (KEY[1]),
.L (KEY[2]),
.Q (LEDR[1])
);
MUXDFF inst4(
.clk (KEY[0]),
.w (LEDR[1]),
.R (SW[0]),
.E (KEY[1]),
.L (KEY[2]),
.Q (LEDR[0])
);
endmodule
module MUXDFF (
input clk,
input w, R, E, L,
output Q
);
always@(posedge clk)begin
Q <= L ? R : (E ? w : Q);
end
endmodule
3-input LUT
题目:
在这个问题中,你将为一个8x1存储器设计一个电路,在这个电路中,写入到存储器是通过移位来完成的,而读取是“随机访问”,就像在一个典型的RAM中一样。然后您将使用该电路实现一个3输入逻辑功能。
首先,用8个D触发器创建一个8位移位寄存器。标记D触发器的输出分别为Q[0]到Q[7]。移位寄存器输入称为S,输入Q[0] (MSB先移位)。使能输入enable控制是否移位,扩展电路使其有3个额外的输入A,B,C和一个输出Z。电路的行为应该如下:当ABC为000时,Z=Q[0],当ABC为001时,Z=Q[1],以此类推。你的电路应该只包含8位移位寄存器和多路复用器。(这个电路称为3输入查找表(LUT))。
个人思路:
意思就是输入的时候是个移位寄存器,而输出是根据“地址”来“随机读取”,其实就是LUT查找表的结构,是xlinx的fpga的最小结构单元之一。
module top_module (
input clk,
input enable,
input S,
input A, B, C,
output Z );
reg [7:0] Q;
always@(posedge clk)begin
if(enable)begin
Q <= {Q[6:0], S};
end
else begin
Q <= Q;
end
end
assign Z = Q[{A, B, C}];
endmodule
更多推荐


所有评论(0)