设计一个伪随机序列发生器,采用的生成多项式为1+x^3+X^7。要求: (1) 具有一个RESET端和两个控制端来调整寄存器初值(程序中设定好四种非零初值可选)。(2) 将生成的伪随机序列在数码管上显示。
基于Monster 组和GPT的调写:
以下是一个使用HDL语言设计的基本伪随机序列发生器,使用的生成多项式为 |+x~3+X^7。它包括一个RESET端和两个控制端,用于调整寄存器的初始值,并且可以将生成的伪随机序列显示在数码管上。
module pseudo_random_seq(
input clk,
input rst,
input ctrl1,
input ctrl2,
output reg [7:0] display
);
reg [6:0] shift_reg;
always @(posedge clk or posedge rst) begin
if (rst) begin
shift_reg <= 7'b0000001;
end else begin
shift_reg <= {shift_reg[5:0], shift_reg[6]^shift_reg[3]};
if (ctrl1) begin
shift_reg <= 7'b0000011;
end else if (ctrl2) begin
shift_reg <= 7'b0000111;
end
end
end
assign display = shift_reg;
endmodule
这个模块具有一个时钟输入和一个重置输入,以及两个控制输入。使用时钟触发,模块会按照生成多项式进行伪随机序列的生成。在每个时钟上升沿的时候,序列会向左移动一位并且计算下一位的值。如果RESET为高电平,则寄存器被重置为初始值;如果ctrl1或ctrl2为高电平,则寄存器将被设置为四种预定义的非零初始值之一。
最后,将生成的伪随机序列输出到一个八位数码管上,以显示当前的序列值。在此示例中,使用display变量将移位寄存器中的当前值输出到数码管中。
参考GPT和自己的思路,下面是一个基于Verilog HDL语言实现的伪随机序列发生器,采用生成多项式1+x^3+x^7。该发生器具有RESET端和两个控制端,以设置寄存器的初始值,同时将生成的伪随机序列在数码管上显示。
module PRBS(
input clk, // 时钟信号
input rst, // 复位信号
input ctrl1, // 控制信号1
input ctrl2, // 控制信号2
output reg [7:0] led // 数码管输出
);
reg [7:0] shift_reg; // 移位寄存器
reg [2:0] control; // 控制信号
always @(posedge clk, negedge rst) begin
if(~rst) begin // 复位信号
shift_reg <= 8'h0;
control <= 3'b0;
end else begin
if(ctrl1) begin // 设置寄存器初值
case(control)
3'b000: shift_reg <= 8'h01;
3'b001: shift_reg <= 8'h7E;
3'b010: shift_reg <= 8'hAA;
3'b011: shift_reg <= 8'h55;
default: shift_reg <= 8'h0;
endcase
control <= control + 1;
end else if(ctrl2) begin // 反转寄存器初值
shift_reg <= ~shift_reg;
end else begin
// 移位操作,生成伪随机序列
shift_reg <= {shift_reg[6:0], shift_reg[7] ^ shift_reg[3] ^ shift_reg[0]};
end
end
end
// 数码管驱动模块,实现BCD码转换并在数码管上显示
display_7seg displayer(shift_reg, led);
endmodule
// 数码管驱动模块
module display_7seg(
input [7:0] num, // 要显示的数字
output reg [7:0] seg // 数码管输出
);
reg [3:0] bcd; // BCD码
// BCD码转换
always @* begin
case(num)
8'h00: bcd = 4'b0000;
8'h01: bcd = 4'b0001;
8'h02: bcd = 4'b0010;
8'h03: bcd = 4'b0011;
8'h04: bcd = 4'b0100;
8'h05: bcd = 4'b0101;
8'h06: bcd = 4'b0110;
8'h07: bcd = 4'b0111;
8'h08: bcd = 4'b1000;
8'h09: bcd = 4'b1001;
8'h0A: bcd = 4'b1010;
8'h0B: bcd = 4'b1011;
8'h0C: bcd = 4'b1100;
8'h0D: bcd = 4'b1101;
8'h0E: bcd = 4'b1110;
8'h0F: bcd = 4'b1111;
default: bcd = 4'bXXXX; // 非法BCD码
endcase
end
// 显示BCD码
always @* begin
case(bcd)
4'b0000: display = 7'b1000000; // 显示0
4'b0001: display = 7'b1111001; // 显示1
4'b0010: display = 7'b0100100; // 显示2
4'b0011: display = 7'b0110000; // 显示3
4'b0100: display = 7'b0011001; // 显示4
4'b0101: display = 7'b0010010; // 显示5
4'b0110: display = 7'b0000010; // 显示6
4'b0111: display = 7'b1111000; // 显示7
4'b1000: display = 7'b0000000; // 显示8
4'b1001: display = 7'b0010000; // 显示9
4'b1010: display = 7'b0001000; // 显示A
4'b1011: display = 7'b0000011; // 显示B
4'b1100: display = 7'b1000110; // 显示C
4'b1101: display = 7'b0100001; // 显示D
4'b1110: display = 7'b0000110; // 显示E
4'b1111: display = 7'b0001110; // 显示F
default: display = 7'b1111111; // 不显示
endcase
end
// 伪随机序列发生器
reg [7:0] shift_reg = 8'h7F; // 初始值为7FH
always @(posedge clk or negedge reset) begin
if (!reset) begin
shift_reg <= 8'h7F;
end else begin
shift_reg <= {shift_reg[6]^shift_reg[0], shift_reg[7:1]};
end
end
// 选择控制信号
wire [1:0] ctrl = {sw[2], sw[1]};
// 设置初值
always @* begin
case(ctrl)
2'b00: shift_reg = 8'h7F; // 初始值为7FH
2'b01: shift_reg = 8'h3D; // 初始值为3DH
2'b10: shift_reg = 8'h5E; // 初始值为5EH
2'b11: shift_reg = 8'h6A; // 初始值为6AH
default: shift_reg = 8'h7F; // 默认初始值为7FH
endcase
end
// 数码管显示控制
reg [3:0] cnt = 4'b0000; // 显示计数器
reg [3:0] index = 4'b0000; // 数码管位选计数器
wire [6:0] segment = display; // 数码管段选信号
reg [3:0] buffer [0:3]; // 数码管缓存
// 数码管扫描
always @(posedge clk) begin
if (reset) begin // 复位
cnt <= 4'b0000;
index <= 4'b0000;
buffer <= 4'b0000;
end
else begin
cnt <= cnt + 1; // 显示计数器自增
if (cnt == 4'b1000) begin
cnt <= 4'b0000;
index <= index + 1; // 数码管位选计数器自增
if (index == 4'b0100) // 最后一位后回到第一位
index <= 4'b0000;
end
end
end
// 数码管数据缓存
always @(posedge clk) begin
if (reset) // 复位
buffer <= 4'b0000;
else begin
case (index) // 根据当前位选计数器的值更新相应的缓存值
4'b0000: buffer[0] <= num;
4'b0001: buffer[1] <= num;
4'b0010: buffer[2] <= num;
4'b0011: buffer[3] <= num;
endcase
end
end
// 数码管段选控制
assign display = segment[index] ? buffer[index] : 7'b111_1111; // 根据位选控制信号选择显示的数值或不显示
// 数码管共阴极控制
assign cathode = 4'b1110 - index; // 根据位选控制信号计算激活的共阴极,因为我们使用的是共阴极的数码管
always @(posedge clk) begin
if (rst) begin
cnt <= 4'b0000;
index <= 4'b0000;
buffer <= 4'b0000;
end
else begin
if (cnt == 4'b1000) begin // 8个时钟周期后更新显示
cnt <= 4'b0000;
index <= index + 1;
if (index == 4'b1000) // 四个数码管显示完毕后回到第一个
index <= 4'b0000;
end
else begin
cnt <= cnt + 1;
buffer[index] <= bcd_data;
end
end
end
assign display = { // 根据当前位选和缓存中的数据计算数码管段选信号
buffer[3][seg],
buffer[2][seg],
buffer[1][seg],
buffer[0][seg]
};
该回答引用ChatGPT
以下是完整的Verilog代码:
module prbs_generator (
input wire clk,
input wire reset,
input wire [1:0] control,
output reg [3:0] display
);
reg [7:0] state;
always @(posedge clk) begin
if (reset) begin
// 清零寄存器
state <= 8'h00;
end else begin
// 选择初始值
case (control)
2'b00: state <= 8'h5F;
2'b01: state <= 8'h3C;
2'b10: state <= 8'h9A;
2'b11: state <= 8'h1E;
endcase
// 生成新状态
state <= {state[6]^state[3], state[7:1]};
end
end
always @(*) begin
case (state)
8'h00: display = 4'b0111;
8'h01: display = 4'b0001;
8'h02: display = 4'b1011;
8'h03: display = 4'b1000;
8'h04: display = 4'b1100;
8'h05: display = 4'b1001;
8'h06: display = 4'b1111;
8'h07: display = 4'b0000;
8'h08: display = 4'b1110;
8'h09: display = 4'b1001;
8'h0A: display = 4'b1111;
8'h0B: display = 4'b1101;
8'h0C: display = 4'b0110;
8'h0D: display = 4'b1111;
8'h0E: display = 4'b1101;
8'h0F: display = 4'b0111;
default: display = 4'b1111;
endcase
end
endmodule
在上面的代码中,我们首先定义了一个名为prbs_generator的模块,它有一个时钟端clk、一个清零端reset、两个控制端control和一个四位数码管输出display。接下来,我们定义了一个8位寄存器state,它用于保存当前的状态。在时钟上升沿时,如果reset为1,我们将寄存器清零。否则,我们根据control的值选择不同的初始值,并根据多项式1+x^3+x^7生成新的状态。最后,我们将状态映射到数码管上,然后将结果输出到display端口。
注意,我们在最后的always块中使用了@()来指示这是一个组合逻辑块。这意味着当state的值发生变化时,display的值将立即被更新。由于这个块没有时钟边沿触发,因此我们使用@()来防止产生无限循环的行为。
module PRNG(
input clk, // 时钟信号
input reset, // 复位信号
input [1:0] ctrl, // 控制信号,用于设置初始值
output reg [7:0] out // 数码管输出信号
);
reg [7:0] reg; // 寄存器
reg [7:0] poly = 8'b10000011; // 生成多项式
always @(posedge clk or posedge reset) begin
if (reset) begin // 复位信号为1,将寄存器清零
reg <= 0;
end else begin
case (ctrl) // 根据控制信号设置寄存器的初始值
2'b00: reg <= 8'h01;
2'b01: reg <= 8'h07;
2'b10: reg <= 8'h1F;
2'b11: reg <= 8'h3F;
default: reg <= 0; // 默认值为0
endcase
for (int i = 0; i < 8; i++) begin
reg <= {reg[6:0], reg[7]} ^ (reg & poly);
end
out <= reg; // 将寄存器的值输出到数码管
end
end
endmodule
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
设计思路:
定义生成多项式为1+x^3+x^7
采用7位寄存器来存储序列,即R7~R1
在每一个时钟上升沿,右移1位,并计算新的R1的值
计算R1的值:R1 = R7 xor R3 xor 1
RESET置位时,将所有寄存器清零
启用控制端时,根据控制端的信号,选择四种非零的初值
将当前的R7数字通过数码管的方式进行显示
HDL代码如下:
module LFSR(
input clk,
input reset,
input [1:0] control,
output reg [6:0] out
);
reg [6:0] register[0:7];
reg feedback;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
for (int i = 0; i < 8; i = i+1)
register[i] <= 0;
end
else
begin
feedback = register[7] ^ register[3] ^ 1;
for (int i = 7; i > 0; i = i-1)
register[i] <= register[i-1];
register[0] <= feedback;
end
end
always @ (register[7])
begin
case(register[7])
2'b00: out <= 7'b0000011; // 初始值为0
2'b01: out <= 7'b0001100; // 初始值为1
2'b10: out <= 7'b0011000; // 初始值为2
2'b11: out <= 7'b0100100; // 初始值为3
default: out <= 7'b1111111; // 非法输入,将数码管全灭
endcase
end
always @ (control)
begin
case(control)
2'b00: register <= 8'b00000001; // 初始值为1
2'b01: register <= 8'b00000101; // 初始值为5
2'b10: register <= 8'b00110011; // 初始值为51
2'b11: register <= 8'b00000010; // 初始值为2
default: register <= 8'b00000000; // 非法输入,所有寄存器清零
endcase
end
endmodule
其中,out输出到数码管上,分别为abcdefg,按照顺序对应7到1位。 control[1:0]用于选择四种不同的初始值。 返回的序列是R7到R1。
需要注意的是,数码管的驱动程序应充分利用时序,以避免串行化延迟造成的错误。
如果我的回答解决了您的问题,请采纳!
本题需要设计一个基于LFSR的伪随机序列发生器。LFSR(线性反馈移位寄存器)是一个常用的伪随机序列发生器,它是由若干个寄存器以及一个带有反馈的多项式构成的。
根据题目要求,我们采用了一个三阶LFSR,生成多项式为/+x^3+X^7,即:
$r_n=r_{n-3}\oplus r_{n-7}$,其中$r_n$表示在时刻$n$时LFSR的寄存器状态。
下面是基于此多项式的设计思路:
考虑到题目要求有四种非零初值可选,我们可以将这四种初值分别存放在一个数组中,通过第一个控制端来选择其中一个。
当一个时钟脉冲到来时,根据上述生成多项式,可知当前的$r_n$值为$r_{n-3}\oplus r_{n-7}$。因此,我们只需要将寄存器的值向左移动一位,然后在最低位进行异或操作即可得到新的寄存器状态。同时,将这个新状态输出至RBSBT端。
我们可以通过将十六进制数值转换成二进制,然后每四位转换成一个十进制数,得到一个长度为8的十进制数。将这个数输出至数码管即可。
下面是伪代码实现:
# 初始化
initial_state = [0b101, 0b110, 0b111] # 四种非零初值可选
state = initial_state[0] # 初始状态为第一个初值
clock_count = 0
display_count = 0
MAX_COUNT = 8 # 每8个时钟脉冲更新数码管一次
DISPLAY = [0, 0, 0, 0, 0, 0, 0, 0]
while True:
# 根据多项式更新状态
feedback = (state >> 4) ^ (state & 0b1)
state = ((state << 1) & 0b111) | feedback
# 将状态输出至RBSBT端
RBSBT.write(state & 0b1)
# 更新时钟脉冲计数器
clock_count += 1
# 根据计数器切换初始状态
if control1.read() == 1:
initial_index = (initial_index + 1) % 4
state = initial_state[initial_index]
# 根据计数器更新数码管显示
if clock_count == MAX_COUNT:
# 将状态转换成8位二进制数
binary_state = bin(state)[2:].zfill(8)
# 将二进制数每四位转换成一个十进制数
for i in range(8):
DISPLAY[i] = int(binary_state[4*i:4*(i+1)], 2)
# 将更新后的数码管显示
display.update(DISPLAY)
# 更新计数器和状态
clock_count = 0
display_count += 1