⭐本专栏针对 FPGA 进行入门学习,从数电中常见的逻辑代数讲起,结合 Verilog HDL 语言学习与仿真,主要对组合逻辑电路与时序逻辑电路进行分析与设计,对状态机 FSM 进行剖析与建模。
🔥文章和代码已归档至【Github 仓库:hardware-tutorial】,需要的朋友们自取。或者关注公众号【AIShareLab】,回复 FPGA 也可获取。
寄存器及 Verilog HDL 建模
图中,PD3~PD0是 4 位数据输入端,
例 试对上图所示的寄存器进行建模。
module Reg4bit (Q,PD,CP,CLR_,Load);
output reg [3:0] Q;
input wire [3:0] PD;
input CP,CLR_,Load;
always @(posedge CP or negedge CLR_)
if (!CLR_) // 异步复位
Q <= 4'b0000;
else if (Load) // 同步加载(置数)
Q <= PD;
else
Q <= Q; // 数据保持
endmodule
复制代码
例 试对图所示任意位数(带参数)的寄存器进行建模。
module Register //Verilog 2001, 2005 syntax
#(parameter N = 8) //定义参数 N = 8
(output reg [N-1:0]Q, //数据输出端口及变量的数据类型声明
input wire [N-1:0]PD,//并行数据输入
input CP, //输入端口声明
input CLR_,
input Load
);
always @(posedge CP or negedge CLR_)
if (~CLR_) // 异步复位
Q <= 0;
else if (Load) // 同步加载(置数)
Q <= PD;
else
Q <= Q; // 数据保持
endmodule
复制代码
移位寄存器及 Verilog HDL 建模
(1) 移位寄存器
将若干个 D 触发器串接级联在一起构成的具有移位功能的寄存器,叫做移位寄存器。
移位寄存器的逻辑功能分类
(2) 4 位单向右移移位寄存器
电路
工作原理
写出激励方程:
$$D_{0}=D_{\mathrm{SI}} \quad \boldsymbol{D}{1}=\boldsymbol{Q}{0}{ }^{n} \quad \boldsymbol{D}{2}=\boldsymbol{Q}{1}^{n} \quad \boldsymbol{D}{3}=\boldsymbol{Q}{2}^{n}$$
写出状态方程:
Q0n+1=DSIQ1n+1=D1=Q0n\Q2n+1=D2=Q1nQ3n+1=D3=Q2n
DSI=11010000,从高位开始输入
经过 7 个 CP 脉冲作用后,从 DSI 端串行输入的数码就可以从 DO 端串行输出。
(3)多功能移位寄存器工作模式简图
右移: DIR→Q0→Q1→Q2→Q3→DOR (左入右出)
左移: DOL←Q0←Q1←Q2←Q3←DI (右入左出)
右移输入并行输出: DIR→Q0→Q1→Q2→Q3 (4 个 CP)
左移输入并行输出: Q0←Q1←Q2←Q3←DII (4 个 CP )
并行输入并行输出、并行输入串行输出。
与普通移位寄存器的连接不同,输入端 D 连接两个不同的数据源,一个数据源为前级的输出,用于移位寄存器的操作;另一个数据来自于外部输入,作为并行操作的一部分。
控制信号 Mode 用来选择操作的模式,
并行存取的移位寄存器
将移位寄存器的DSO(Q3)与DIN相连,则构成环形计数器,如图所示。
若事先通过 PE 端施加低电平脉冲, 将初始数据 Q0Q1Q2Q3=1000 置入触发器中,
在 CP 脉冲用下, Q0Q1Q2Q3 将依次为 1000→0100→0010→0001→1000→⋯⋯ , 即每个触发器经 过 4 个时钟周期输出一个高电平脉冲, 并且该高电平脉冲 沿环形路径在触发器中传递。可见, 4 个触发器只有 4 个计数状态。
约翰逊计数器(Johnson Counter)
如果将图 4.4.3 电路中的Q3与 DIN 相连,则构成扭环形计数器,亦称为约翰逊计数器(Johnson Counter),电路的状态将增加一倍。
例 试对下图所示的右向移位寄存器进行建模。
module ShiftReg (Q,Din,CP,CLR_);
input Din; //Serial Data inputs
input CP, CLR_; //Clock and Reset
output reg [3:0] Q; //Register output
always @ (posedge CP or negedge CLR_)
if (~CLR_) //asynchronous clear
Q <= 4'b0000;
else begin //Shift right
Q[0] <= Din;
Q[3:1] <= Q[2:0];
end
endmodule
复制代码
例 一个 4 位的双向移位寄存器框图如图所示。该寄存器有两个控制输入端(S1、S0)、两个串行数据输入端(Dsl、Dsr)、4 个并行数据输入端和 4 个并行输出端,要求实现 5 种功能:异步置零、同步置数、左移、右移和保持原状态不变,其功能如表所示。试用功能描述风格对其建模。
module UniversalShift (S1,S0,Din,Dsl,Dsr,Q,CP,CLR_);
input S1, S0; //Select inputs
input Dsl, Dsr; //Serial Data inputs
input CP, CLR_; //Clock and Reset
input [3:0] Din; //Parallel Data input
output reg [3:0] Q; //Register output
always @ (posedge CP or negedge CLR_)
if (~CLR_) //asynchronous clear
Q <= 4'b0000;
else
case ({S1,S0})
2'b00: Q <= Q; //No change
2'b01: Q <= {Dsr,Q[3:1]}; //Shift right
2'b10: Q <= {Q[2:0],Dsl}; //Shift left
2'b11: Q <= Din; //Parallel load input
endcase
endmodule
复制代码
移位寄存器的应用电路
(1) 开关去“抖动” 电路
module Debounce (Out,Btn_In,CLK,CLR_);
input [3:0] Btn_In; //Button inputs
input CLK, CLR_; //Clock and Reset
output [3:0] Out; //Register output
reg [3:0] Delay0;
reg [3:0] Delay1;
reg [3:0] Delay2;
always @ (posedge CLK or negedge CLR_)
begin
if (~CLR_) begin //asynchronous clear
Delay0 <= 4’b0000;
Delay1 <= 4’b0000;
Delay2 <= 4’b0000;
end
else begin //Shift right
Delay0 <= Btn_In;
Delay1 <= Delay0;
Delay2 <= Delay1;
end
end
assign Out = Delay0 & Delay1 & Delay2;
endmodule
复制代码
(2) 单脉冲产生电路
(1)设计块:单脉冲产生电路的代码如下:
module ClockPulse (Out, Btn_In,CLK,CLR_);
input Btn_In; //Button inputs
input CLK, CLR_; //Clock and Reset
output Out; //Output
reg Delay0;
reg Delay1;
reg Delay2;
always @ (posedge CLK or negedge CLR_)
begin
if (~CLR_) //asynchronous clear
{Delay0, Delay1, Delay2} <= 3’b000;
else begin //Shift right
Delay0 <= Btn_In;
Delay1 <= Delay0;
Delay2 <= Delay1;
end
end
assign Out = Delay0 & Delay1 & ~Delay2;
endmodule
复制代码
(2)激励块:给输入(CLR_、Btn_In 和 CLK)赋值,产生激励信号。
module Test_ClockPulse ;
reg Btn_In; //Button inputs
reg CLK, CLR_; //Clock and Reset
wire Out; //single clock pulse output
ClockPulse U0(Out, Btn_In,CLK,CLR_);
initial begin // CLR_
CLR_ = 1'b0;
CLR_ = #20 1'b1;
#350 $stop; //总仿真时间为370
end
always begin // CLK
CLK = 1'b0;
CLK = #10 1'b1;
#10;
end
复制代码
initial begin // Btn_In
Btn_In = 1'b0;
Btn_In = #30 1'b1;
Btn_In = #5 1'b0;
Btn_In = #5 1'b1;
Btn_In = #20 1'b0;
#100;
Btn_In = 1'b1;
Btn_In = #5 1'b0;
Btn_In = #5 1'b1;
Btn_In = #80 1'b0;
end
endmodule
复制代码
(3) 仿真波形
欢迎关注公众号【AIShareLab】,一起交流更多相关知识,前沿算法,Paper 解读,项目源码,面经总结。
评论