微信公众号获取更多FPGA相关源码:
1.触发器
(1)有两个稳定状态(简称稳态),正好用来表示逻辑 0 和 1。
(2)在输入信号作用下,触发器的两个稳定状态可相互转换(称为状态的翻转)。输入信号消失后,新状态可长期保持下来,因此具有记忆功能,可存储二进制信息。
(3)一个触发器可存储 1 位二进制数码。
(4)触发器有记忆功能,由它构成的电路在某时刻的输出不仅取决于该时刻的输入,还与电路原来状态有关。而门电路无记忆功能,由它构成的电路在某时刻的输出完全取决于该时刻的输入,与电路原来状态无关。
(5)触发器和门电路是构成数字电路的基本单元。
2.由触发器构成寄存器
D触发器可用于存储比特信号,增加一根输入线load,可加载输入信号。
边沿触发的存储单元,在上升沿(或下降沿)数据变化,一个周期里只能变化一次。
用来暂时存放参与运算的数据和运算结果。在实际的数字系统中,通常把能够用来存储一组二进制代码的同步时序逻辑电路称为寄存器。
可以把4个1位寄存器模块组合在一起,构成4位的寄存器,同理,可以用N个1位寄存器构造成1个N位寄存器。
3.移位寄存器
移位寄存器是一种在时钟脉冲的作用下,将寄存器中的数据按位移动的逻辑。
1个N位的移位寄存器包含N个触发器。在每个时钟脉冲下,数据从一个触发器移到另一个触发器。需要注意的是,在同一时钟上升沿,所有的数值都是同时移位的。
移位寄存器不但可以用来寄存数据,还可以用来实现数据的串并转换、延时、数值运算以及其他电路设计
电路主要功能:
- 串行输入串行输出
- 串行输入并行输出
- 并行输入串行输出
在时钟边沿触发的移位寄存器:
reg [15:0] myreg;
always @(posedge clk)
myreg <= {myreg[14:0],data_in};
在此示例中,myreg 数据向左移动,并添加 data_in,最高有效位被丢弃。
4.移位寄存器的应用
4.1流水灯
always @(posedge clk or negedge rst)
begin
if (!rst)
dout = din;
else
case(ctl)
0: dout = {dout[1], dout[8:2]}; //从左向右循环移动(右移)
1: dout = {dout[7:1], dout[8]}; //从右向左循环移动(左移)
2: dout = {dout [7:5], dout [8], d[3:1], dout [4]};
//前4位与后4位分别循环左移
3: dout = {dout [5], dout [8:6], dout [1], dout [4:2]};
//前4位与后4位分别循环右移
default: dout = din;
4.2 并串转换和串并转换
串行电路分类:
- 同步串口:SPI和I2C等
- 异步串口:RS232、RS485等
串行电路优点:
- 引脚资源消耗少
- 干扰小
如果与串行电路接口,通常会包含串并转换和并串转换两部分电路:
4.2.1串入串出移位寄存器
8位移位寄存器由8个D触发器串联构成,在时钟信号的作用下,前级的数据向后移动
串入串出移位寄存器verilog实现代码:
module shift_1(din,clk,dout);
input din,clk;
output reg dout;
reg tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7;
always@(posedge clk)
begin
tmp1<=din;
tmp2<=tmp1;
tmp3<=tmp2;
tmp4<=tmp3;
tmp5<=tmp4;
tmp6<=tmp5;
tmp7<=tmp6;
dout<=tmp7;
end
endmodule
4.2.2串入并出移位寄存器
使用触发器可以实现移位寄存器对数据的串-并转换。
4位串行输入并行输出移位寄存器的逻辑电路如下图所示。该寄存器由4个同步D触发器组成,这种D触发器的CLRN端是异步清零端。
串入并出移位寄存器verilog实现代码:
module shift_2(din,clk,clr,q);
input din,clk,clr;
output [3:0] q;
reg [3:0] q;
always@(posedge clk , negedge clr) begin
if(clr==1’b0)
q<=4’b0000;
else begin
q[0]<= din;
q <= q<<1;
end
end
endmodule
其中always块里面,else部分可以替换:
等价于下面的代码:
module shift_2(din,clk,clr,q);
input din,clk,clr;
output [3:0] q;
reg [3:0] q;
always@(posedge clk , negedge clr) begin
if(clr==1’b0)
q<=4’b0000;
else begin
q[0]<=din;
q[1]<=q[0];
q[2]<=q[1];
q[3]<=q[2];
end
endmodule
4.2.3并入串出移位寄存器
并入串出移位寄存器可以将一组二进制数并行送入一组寄存器,然后把这些数据串行从寄存器内输出。
一个同步并入串出移位寄存器的基本管脚:
- 并行输出输入端:data
- 时钟脉冲输入端:clk
- 加载数据端:load
- 串行数据输出端:dout
并入串出移位寄存器Verilog实现代码:
方法一:
module shift3 (clk,din, load,q);
input clk,load;
input [3:0] din;
output reg q;
reg [3:0] tmp;
always@(posedge clk)
begin
if(load==1’b1)
tmp<=din;
else begin
tmp<=tmp<<1;
tmp[0]<=1’b0;
q<=tmp[3];
end
end
endmodule
方法二:
module shift3 (clk,din, load,q);
input clk,load;
input [3:0] din;
output q;
reg [3:0] tmp;
always@(posedge clk)
if(load)
tmp<=din;
else
tmp[3:1]<=tmp[2:0];//左移
assign q=tmp[3];
endmodule
方法二是从最高位串行输出;若要求从最低位串行输出,则只需修改tmp[2:0]<=tmp[3:1];与assign q=tmp[0]; 即右移。
8位通用移位寄存器verilog实现代码:
module univ_shift_reg #(parameter N=8) (
input clk, reset;
input [1:0] ctrl;
input [N-1:0] d;
output [N-1:0] q );
reg [N-1:0] r_reg, r_next;
always@(posedge clk, posedge reset)
if(reset) r_reg<=0;
else r_reg<= r_next;
always@(*)
case (ctrl)
2’b00: r_next = r_reg; //无操作
2’b01: r_next = {r_reg[N-2:0], d[0]}; //左移
2’b10: r_next = {d[N-1], r_reg[N-1:1]}; //右移
default: r_next= d; //载入
endcase
assign q=r_reg;
endmodule
以上都是不带AXI协议的串并、并串转换,带有AXI Stream协议的串并、并串转换,请看文章:基于valid-ready双向握手机制的串并和并串转换
链接:https://mp.weixin.qq.com/s/9j6zz69i37CcWAnsfm1ePQ
微信公众号获取更多FPGA相关源码: