在这里插入图片描述



数字IC经典电路设计

经典电路设计是数字IC设计里基础中的基础,盖大房子的第一部是打造结实可靠的地基,每一篇笔者都会分门别类给出设计原理、设计方法、verilog代码、Testbench、仿真波形。然而实际的数字IC设计过程中考虑的问题远多于此,通过本系列希望大家对数字IC中一些经典电路的设计有初步入门了解。能力有限,纰漏难免,欢迎大家交流指正。

快速导航链接如下:

个人主页链接

1.数字分频器设计

2.序列检测器设计

3.序列发生器设计

4.序列模三检测器设计

5.奇偶校验器设计

6.自然二进制数与格雷码转换



一、前言

什么是移位寄存器?

组成:由具有存储功能的触发器构成。另外,寄存器还应有执行数据接收和清除命令的控制电路,一般由门电路构成。
功能:移位寄存器可寄存一组二值代码,N个触发器组成的寄存器可以存储一组N位的二值代码,一般用于将二进制数据从一个位置转移到另一个位置

移位寄存器有哪些分类呢?

  • 按移位方向分类:①单向移位寄存器(包括左移、右移)②双向移位寄存器
  • 按循环方式分类:①循环移位寄存器②非循环移位寄存器
  • 按部位的不同分类:①逻辑移位寄存器②算术移位寄存器
  • 按输入输出方式分类:①串入串出②串入并出③并入串出④并入并出

二、简单循环左移/右移/双向移位寄存器

2.1 简单循环左移/右移/双向移位寄存器

(1)右移移位寄存器

在这里插入图片描述

(2)左移移位寄存器
在这里插入图片描述

(3)双向移位寄存器

在这里插入图片描述

为便于扩展逻辑功能和增加使用的灵活性,在单向移位寄存器基础上,增加由门电路组成的控制电路,便可构成双向移位寄存器。目前,在定型生产的中规模移位寄存器集成电路上除了附加左、右移控制,一般还附有数据并行输入、保持、异步置零(复位)等功能。

一般双向移位寄存器逻辑图示例:

在这里插入图片描述

2.2 verilog代码

要求:设计一个四位循环移位寄存器,包括三种移位寄存器,分别是左移移位寄存器、右移移位寄存器、双向移位寄存器。

//三个四位宽的循环移位寄存器
//左移移位寄存器、右移移位寄存器、双向移位寄存器
module sr_simple #(
    parameter WIDTH = 4	//定义数据位宽
    )(
    input    clk,
    input    rst_n,
    input    [1:0]  model,		//双向移位寄存器输出模式选择
    input    [WIDTH - 1 : 0]    data_in,
    output   [WIDTH - 1 : 0]    data_left,	//左移移位寄存器输出
    output   [WIDTH - 1 : 0]    data_right,	//右移移位寄存器输出
    output   [WIDTH - 1 : 0]    data_bidi	//双向移位寄存器输出
    );

//定义双向移位寄存器三种状态——保持、左移、右移
parameter keep = 2'b00;
parameter left_shift = 2'b01;
parameter right_shift = 2'b10;

//左移移位寄存器工作模块
//借助拼接符实现移位
reg [WIDTH - 1 : 0] data_left_r; //中间寄存器
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_left_r <= data_in;
end
else begin
data_left_r <= { data_left_r[WIDTH - 2 : 0], data_left_r[WIDTH - 1]};
end
end

//右移移位寄存器工作模块
//借助拼接符实现移位
reg [WIDTH - 1 : 0] data_right_r; //中间寄存器
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_right_r <= data_in;
end
else begin
data_right_r <= { data_right_r[0],data_right_r[WIDTH - 1 : 1]};
end
end

//双向移位寄存器工作模块
//借助拼接符实现移位,case语句实现状态选择
reg [WIDTH - 1 : 0] data_bidi_r; //中间寄存器
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_bidi_r <= data_in;
end
else begin
case(model)
keep: data_bidi_r <= data_bidi_r;
left_shift: data_bidi_r <= { data_bidi_r[WIDTH - 2 : 0], data_bidi_r[WIDTH - 1]};
right_shift: data_bidi_r <= { data_bidi_r[0],data_bidi_r[WIDTH - 1 : 1]};
default: data_bidi_r <= data_bidi_r;
endcase
end
end

//组合逻辑输出
assign data_left = data_left_r;
assign data_right = data_right_r;
assign data_bidi = data_bidi_r;

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

2.3 Testbench

`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sr_simple_tb #(
    parameter WIDTH = 4	//定义数据位宽
    );

//信号申明
reg clk;
reg rst_n;
reg [1:0] model;
reg [WIDTH - 1 : 0] data_in;
wire [WIDTH - 1 : 0] data_left;
wire [WIDTH - 1 : 0] data_right;
wire [WIDTH - 1 : 0] data_bidi;

//模块实例化(将申明的信号连接起来即可)
sr_simple u_sr_simple(
.clk (clk),
.rst_n (rst_n),
.model (model),
.data_in (data_in),
.data_left (data_left),
.data_right (data_right),
.data_bidi (data_bidi)
);

always #5 clk = ~clk; //生成时钟信号

//调用系统命令——监视
initial begin
$monitor (“rst_n = %b, data_in = %b, data_left = %b, data_right = %b, model = %b,data_bidi = %b”,
rst_n, data_in, data_left, data_right,model,data_bidi);
end

//为输入数据赋值
initial begin
clk = 0;
rst_n = 1;
data_in = 4'b1001;
model = 2'b00;
#5 rst_n = 0;
#5 rst_n = 1;
#40 model = 2'b01;
#40 model = 2'b00;
#40 model = 2'b10;
#100 $finsh;
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2.4 仿真结果

在这里插入图片描述

在这里插入图片描述

三、逻辑移位与算术移位寄存器

3.1 逻辑移位与算术移位寄存器

逻辑移位与算术移位寄存器均属于非循环移位寄存器;

逻辑移位:逻辑移位是指逻辑左移和逻辑右移,移出的空位都用0来补。

算术移位:算术移位就需要分有符号型值和无符号型值。对于无符号型值,算术移位等同于逻辑移位;而对于有符号型值,算术左移等同于逻辑左移,算术右移补的是符号位,正数补0,负数补1。

简而言之,两者的区别在于:逻辑移位不考虑符号位,左移和右移都只补零;算术移位考虑符号位,左移补零,右移补符号位。

对于二进制的数值来说右移n位等于原来的数值除以2的n次方
​Tips:这种倍数关系只适用于右移后被舍弃的低位不含1的情况,否则每舍一次1则代表余数被舍去,保留整数部分。

比如10110100十进制是76(需要先将这个补码转换成原码之后再转换成十进制),右移两位后是11101101转成十进制是19恰好是76的4倍。但是101十进制是5,逻辑右移一位是010十进制是2,此时舍掉了余数1;

3.2 verilog代码

要求:设计一个四位非循环移位寄存器,可实现逻辑右边移和算术右移(逻辑左移和算术左移相同,此处不做展开)。

//四位宽非循环移位寄存器
//可实现逻辑右边移和算术右移
module sr_log_ari #(
    parameter	WIDTH = 4	//定义数据位宽
    )(
    input		 clk,
    input 		 rst_n, 
    input  [WIDTH - 1:0] data_in,
    output [WIDTH - 1:0] data_log,	//逻辑右移输出
    output [WIDTH - 1:0] data_ari	//算术右移输出
    ); 

//逻辑移位工作模块
reg [WIDTH -1:0] data_log_r;//中间寄存器
always@(posedge clk or posedge rst_n)begin
if(!rst_n) begin
data_log_r <= data_in;
end
else begin
data_log_r <= { 1'b0,data_log_r[WIDTH - 1:1]};
end
end

//算术移位工作模块
reg [WIDTH -1:0] data_ari_r;//中间寄存器
always@(posedge clk or posedge rst_n)begin
if(!rst_n) begin
data_ari_r <= data_in;
end
else if(!data_log_r[WIDTH - 1]) begin
data_ari_r <= { 1'b0,data_ari_r[WIDTH - 1:1]};//最高位是“1”则补“1”
end
else begin
data_ari_r <= { 1'b1,data_ari_r[WIDTH - 1:1]};//最高位是“0”则补“0”
end
end

//组合逻辑输出
assign data_log = data_log_r;
assign data_ari = data_ari_r;

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

3.3 Testbench

`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sr_log_ari_tb #(
    parameter WIDTH = 4	//定义数据位宽
    );

///信号申明
reg clk;
reg rst_n;
reg [WIDTH - 1 : 0] data_in;
wire [WIDTH - 1 : 0] data_log;
wire [WIDTH - 1 : 0] data_ari;

//模块实例化(将申明的信号连接起来即可)
sr_log_ari u_sr_log_ari(
.clk (clk),
.rst_n (rst_n),
.data_in (data_in),
.data_log (data_log),
.data_ari (data_ari)
);

always #5 clk = ~clk;//生成时钟信号

//调用系统命令——监视
initial begin
$monitor (“rst_n = %b, data_in = %b, data_log = %b, data_ari = %b”,
rst_n, data_in, data_log, data_ari);
end

//为输入数据赋值
initial begin
clk = 0;
rst_n = 1;
data_in = 4'b1001;
#5 rst_n = 0;
#5 rst_n = 1;
#40;
data_in =4'b0110;
#5 rst_n = 0;
#5 rst_n = 1;
#40 $finsh;
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

3.4 仿真结果

在这里插入图片描述

在这里插入图片描述

四、串-并移位寄存器与并-串移位寄存器

根据存放数码的方式不同分为并行和串行两种:并行方式就是将寄存的数码从各对应的输入端同时输入到寄存器中;串行方式是将数码从一个输入端逐位输入到寄存器中。根据取出数码的方式不同也可分为并行和串行两种:并行方式就是要取出的数码从对应的各个输出端上同时出现;串行方式是被取出的数码在一个输出端逐位输出;

在这里插入图片描述

例如:需要传输的数据有32bit,用串行传输则需要32个时钟周期完成传输,如果用8位并行传输,则32bit数据只需要4个时钟周期就可以完成传输。

根据以上数据输入输出分类,此时有四种移位寄存器:①串入串出②串入并出③并入串出④并入并出。下文将重点对串-并和并串移位寄存器进行分析,并且给出相应verilog代码、Testbench和仿真。
在这里插入图片描述

转换可以采用两种方式实现

  • msb优先(Most Significant Bit):最高比特,即最高位优先
  • lsb优先(Least Significant Bit):最低比特,即最低位优先

4.1串-并移位寄存器

4.1.1串-并移位寄存器

串-并移位寄存器拥有多个存储单元,每个存储单元都可以存储一个二进制数位。当输入一串二进制数据时,时钟信号会依次将每个数据位移入到寄存器的最低位。当所有数据位都被移入后,就可以通过并行输出将数据同时输出到多个接收器上。

4.1.2 verilog代码

要求:实现一个串并转换器,每个时钟周期输入1bit数据,8个时钟周期后数据并行输出,分别采用MSB优先和LSB优先输出。

//1-8串并转换器
module sr_sipo #(
    parameter WIDTH = 8   
    )(
    input    clk,
    input    rst_n,
    input    din,
    output   reg [WIDTH - 1 : 0] dout_msb,//高位优先输出
    output   reg [WIDTH - 1 : 0] dout_lsb//低位优先输出
    );

//计数器实现的8分频模块(开始
//计数器
reg [3:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 4'b0 ;
end
else if (cnt == 3) begin
cnt <= 4'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end

//信号翻转生成8分频信号
reg clk_div8_r;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_div8_r <= 1'b0;
end
else if (cnt == 3 ) begin
clk_div8_r <= ~clk_div8_r;
end
end

assign clk_div8 = clk_div8_r;
//计数器的8分频模块(结束

//移位寄存器模块(开始
//输入先寄存一拍
reg din_r;
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
din_r <= 1'b0;
end
else begin
din_r <= din;
end

//最高位优先输出
reg [WIDTH - 1 : 0] dout_msb_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout_msb_r <= 0;
end
else begin
dout_msb_r <= { dout_msb_r[WIDTH - 2 :0],din_r};
end
end

//最低位优先输出
reg [WIDTH - 1 : 0] dout_lsb_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout_lsb_r <= 0;
end
else begin
dout_lsb_r <= { din_r,dout_lsb_r[WIDTH - 1 :1]};
end
end
//移位寄存器模块(结束

//时序逻辑输出
always@(posedge clk_div8 or negedge rst_n) begin
if(!rst_n) begin
dout_msb <= 0;
dout_lsb <= 0;
end
else begin
dout_msb <= dout_msb_r;
dout_lsb <= dout_lsb_r;
end
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

4.1.3 Testbench
`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sr_sipo_tb #(
    parameter WIDTH = 8
    );

///信号申明
reg clk;
reg rst_n;
reg din;
wire [WIDTH - 1 : 0] dout_msb;
wire [WIDTH - 1 : 0] dout_lsb;

//模块实例化(将申明的信号连接起来即可)
sr_sipo u_sr_sipo(
.clk (clk),
.rst_n (rst_n),
.din (din),
.dout_msb (dout_msb),
.dout_lsb (dout_lsb)
);

always #5 clk = ~clk; //生成时钟信号

//调用系统命令——监视
initial begin
$monitor (“rst_n = %b, din = %b, dout_msb = %b, dout_lsb = %b”,
rst_n, din, dout_msb, dout_lsb);
end

//为输入数据赋值
initial begin
clk = 0;
rst_n = 1;
din = 1'b0;
#5 rst_n = 0;
#5 rst_n = 1;
din =1'b1;
#10 din =1'b0;
#10 din =1'b1;
#10 din =1'b0;
#10 din =1'b1;
#10 din =1'b0;
#10 din =1'b0;
#10 din =1'b1;
#10 din =1'b1;
#200 $finsh;
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

4.1.4 仿真结果

在这里插入图片描述

在这里插入图片描述

4.2并-串移位寄存器

4.2.1并-串移位寄存器

并转串电路主要由时钟(clk)、复位信号(rst_n)、并行输入信号、串行输出信号和使能信号组成。使能信号表示开始执行并转串操作,由于并转串是移位操作,先将八位数据暂存于一个八位寄存器器中,然后左移输出到一位输出端口,通过一个“移位”来实现,当一次并转串完成后,需要重新载入待转换的并行数据时,使能信号要再起来一次。

4.2.2 verilog代码

要求:实现一个并串转换器,每个时钟周期输出1bit数据,8个时钟周期后数据全部输出,分别采用MSB优先和LSB优先输出。

//8-1串并转换器
module sr_piso #(
    parameter WIDTH = 8   
    )(
    input    clk,
    input    rst_n,
    input    [WIDTH - 1 : 0] din,
    output   up_edge,
    output   dout_msb,//高位优先输出
    output   dout_lsb//低位优先输出
    );

//计数器实现的8分频模块(开始
//计数器
reg [3:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 4'b0 ;
end
else if (cnt == 3) begin
cnt <= 4'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end

//信号翻转生成8分频信号
reg clk_div8_r;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_div8_r <= 1'b0;
end
else if (cnt == 3 ) begin
clk_div8_r <= ~clk_div8_r;
end
end

//8分频信号上升沿检测——先寄存一拍
reg clk_div8;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
clk_div8 <= 1'b0;
end
else begin
clk_div8<= clk_div8_r;
end
end

assign up_edge = !clk_div8 & clk_div8_r;//8分频信号上升沿检测——逻辑运算输出
//计数器的8分频模块(结束

//移位寄存器模块(开始
//输入先寄存一拍
reg [WIDTH - 1 : 0] din_r;
always @(posedge clk_div8 or negedge rst_n)
if(!rst_n) begin
din_r <= 0;
end
else begin
din_r <= din;
end

//最高位优先输出
reg [WIDTH - 1 : 0] dout_msb_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout_msb_r <= 0;
end
else if(up_edge) begin
dout_msb_r <= din_r;
end
else begin
dout_msb_r <= { dout_msb_r[WIDTH - 2 :0],1'b0};
end
end

//最低位优先输出
reg [WIDTH - 1 : 0] dout_lsb_r;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
dout_lsb_r <= 0;
end
else if(up_edge) begin
dout_lsb_r <= din_r;
end
else begin
dout_lsb_r <= { 1'b0,dout_lsb_r[WIDTH - 1 :1]};
end
end
//移位寄存器模块(结束

//组合逻辑输出
assign dout_msb = dout_msb_r[WIDTH - 1];
assign dout_lsb = dout_lsb_r[0];

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

4.2.3 Testbench
`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module sr_piso_tb #(
    parameter WIDTH = 8
    );

//信号申明
reg clk;
reg rst_n;
reg [WIDTH - 1 : 0]din;
wire dout_msb;
wire dout_lsb;

//模块实例化(将申明的信号连接起来即可)
sr_piso u_sr_piso(
.clk (clk),
.rst_n (rst_n),
.din (din),
.dout_msb (dout_msb),
.dout_lsb (dout_lsb)
);

always #5 clk = ~clk; //生成时钟信号

//调用系统命令——监视
initial begin
$monitor (“rst_n = %b, din = %b, dout_msb = %b, dout_lsb = %b”,
rst_n, din, dout_msb, dout_lsb);
end

//为输入数据赋值
initial begin
clk = 0;
rst_n = 1;
din = 8'b0;
#5 rst_n = 0;
#5 rst_n = 1;
din =8'b10011010;
#100 din =8'b10101010;
#100 din =8'b11111111;
#200 $finsh;
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

4.2.4 仿真结果

在这里插入图片描述
在这里插入图片描述

五、线性反馈移位寄存器LFSR

此处更详细可以参考线性反馈移位寄存器LFSR(斐波那契LFSR(多到一型)和伽罗瓦LFSR(一到多型)|verilog代码|Testbench|仿真结果)

5.1 斐波那契LFSR

5.1.1 斐波那契LFSR

斐波那契LFSR为多到一型LFSR,即多个触发器的输出经过异或逻辑来驱动一个触发器的输入。反馈多项式为

    f
   
   
    (
   
   
    x
   
   
    )
   
   
    =
   
   
    
     x
    
    
     3
    
   
   
    +
   
   
    
     x
    
    
     2
    
   
   
    +
   
   
    1
   
  
  
   f(x)=x^3 + x^2 +1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 1em; vertical-align: -0.25em;"></span><span class="mord mathnormal" style="margin-right: 0.1076em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right: 0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right: 0.2778em;"></span></span><span class="base"><span class="strut" style="height: 0.8974em; vertical-align: -0.0833em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height: 0.8141em;"><span class="" style="top: -3.063em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right: 0.2222em;"></span></span><span class="base"><span class="strut" style="height: 0.8974em; vertical-align: -0.0833em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height: 0.8141em;"><span class="" style="top: -3.063em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right: 0.2222em;"></span></span><span class="base"><span class="strut" style="height: 0.6444em;"></span><span class="mord">1</span></span></span></span></span>,即<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     1
    
   
  
  
   x_1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输入为<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     3
    
   
  
  
   x_3
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>和<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     2
    
   
  
  
   x_2
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输出异或后的结果,电路图如下所示:<br> <img src="https://i-blog.csdnimg.cn/blog_migrate/d4b6e7ac26d447d191f7542c14bf3545.png#pic_center" alt="在这里插入图片描述"></p> 

输出序列的顺序为:111-110-100-001-010-101-011-111

5.1.2 verilog代码
//三级斐波那契LFSR设计
//反馈多项式为 f(x)=x^3 + x^2 +1
module lfsr_fibonacci(
    input	     	 clk,
    input	     	 rst_n,
    output reg [2:0] q
    );

//时序逻辑LFSR移位模块
always @(posedge clk or rst_n) begin
if (!rst_n) begin
q <= 3'b111; //种子值为111
end
else begin
q <= { q[1],q[0],q[1]^q[2]}; //根据三级斐波那契LFSR电路拼接输出
end
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

5.1.3 Testbench
`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module lfsr_fibonacci_tb();

//信号申明
reg clk;
reg rst_n;
wire [2:0] q;

//模块实例化(将申明的信号连接起来即可)
lfsr_fibonacci u_lfsr_fibonacci(
.clk (clk),
.rst_n (rst_n),
.q (q)
);

always #5 clk = ~clk; //生成时钟信号

//为输入数据赋值
initial begin
clk = 1;
rst_n = 1;
#5 rst_n = 0;
#5 rst_n = 1;
#1000
$stop;
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

5.1.4 仿真结果

在这里插入图片描述

5.2 伽罗瓦LFSR

5.2.1 伽罗瓦LFSR

伽罗瓦LFSR为一到多型LFSR,即一个触发器的输出经过异或逻辑来驱动多个触发器的输入。对于同样的反馈多项式

     x
    
    
     3
    
   
   
    +
   
   
    
     x
    
    
     2
    
   
   
    +
   
   
    1
   
  
  
   x^3+x^2+1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.8974em; vertical-align: -0.0833em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height: 0.8141em;"><span class="" style="top: -3.063em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right: 0.2222em;"></span></span><span class="base"><span class="strut" style="height: 0.8974em; vertical-align: -0.0833em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height: 0.8141em;"><span class="" style="top: -3.063em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right: 0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right: 0.2222em;"></span></span><span class="base"><span class="strut" style="height: 0.6444em;"></span><span class="mord">1</span></span></span></span></span>而言:触发器<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     1
    
   
  
  
   x_1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输入通常来源于触发器<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     2
    
   
  
  
   x_2
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输出,<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     3
    
   
  
  
   x_3
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>(最高项)的输入通常来自于<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     1
    
   
  
  
   x_1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输出,此多项式中剩余触发器的输入是<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    x
   
   
    1
   
  
  
   x1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.6444em;"></span><span class="mord mathnormal">x</span><span class="mord">1</span></span></span></span></span>的输出与前级输出异或的结果,<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     2
    
   
  
  
   x_2
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输入由<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     1
    
   
  
  
   x_1
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输出与<span class="katex--inline"><span class="katex"><span class="katex-mathml">

 
  
   
    
     x
    
    
     3
    
   
  
  
   x_3
  
 
</span><span class="katex-html"><span class="base"><span class="strut" style="height: 0.5806em; vertical-align: -0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height: 0.3011em;"><span class="" style="top: -2.55em; margin-left: 0em; margin-right: 0.05em;"><span class="pstrut" style="height: 2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height: 0.15em;"><span class=""></span></span></span></span></span></span></span></span></span></span>的输出通过异或运算得到。其电路图如下所示:<img src="https://i-blog.csdnimg.cn/blog_migrate/d71d30e0b72fee13a3573dc15981c228.png#pic_center" alt="在这里插入图片描述"></p> 

输出序列的顺序为:111-101-100-010-001-110-011-111

5.2.2 verilog代码
//三级伽罗瓦LFSR设计
//反馈多项式为 f(x)=x^3 + x^2 +1
module lfsr_galois(
    input	     	 clk,
    input	     	 rst_n,
    output reg [2:0] q
    );

//时序逻辑LFSR移位模块
always @(posedge clk or rst_n) begin
if (!rst_n) begin
q <= 3'b111; //种子值为111
end
else begin
q <= { q[0],q[2]^q[0],q[1]}; //根据三级伽罗瓦LFSR电路拼接输出
end
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

5.2.3 Testbench
`timescale 1ns/1ps		//仿真时间单位1ns 仿真时间精度1ps
module lfsr_galois_tb();

//信号申明
reg clk;
reg rst_n;
wire [2:0] q;

//模块实例化(将申明的信号连接起来即可)
lfsr_galois u_lfsr_galois(
.clk (clk),
.rst_n (rst_n),
.q (q)
);

always #5 clk = ~clk; //时钟信号生成

//为输入数据赋值
initial begin
clk = 1;
rst_n = 1;
#5 rst_n = 0;
#5 rst_n = 1;
#1000
$stop;
end

endmodule

AI写代码 c
运行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

5.2.4 仿真结果

在这里插入图片描述

六、总结

简单循环左移/右移/双向移位寄存器:设计简单,主要通过verilog语法中的拼接运算符“{}”完成,双向移位寄存器的设计在左、右移位寄存器的基础上通过case语句(if也行、三目运算符亦可),整体设计偏简单,可应用在序列检测器与序列发生器中。

逻辑移位与算术移位寄存器:最重要的是弄清楚逻辑移位与算术移位的原理、逻辑移位与算术移位的区别(左移一致,仅右移有区别),在此基础上根据上一个简单移位寄存器进行设计。
Tips:逻辑移位与算术移位寄存器是非循环移位寄存器,拼接的时候采用“0”“1”拼接。

串-并移位寄存器与并-串移位寄存器:此处需要强调一点,就是在设计的串并转换时一定要考虑串并数据的时钟周。所以设计时包含以下几个模块:数字分频器和移位寄存器(数字分频器参考数字分频。初此以外,在设计并行的时候还引入了8分频的上升沿检测(当时在这卡壳了很久,或许还有其他更好地方法)。

不定期检查、补充、纠错,欢迎随时交流纠错
最后修改日期:2023.5.15

软件版本:

仿真软件:Modelsim 10.6c
绘图软件:亿图图示
描述语言:verilog

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐