verilog语法实例学习(9)
常用的时序电路介绍
寄存器
一个触发器可以存储一位数据,由n个触发器组成的电路可以存储n位数据,我们把这一组触发器叫做寄存器。寄存器中每个触发器共用同一个时钟。
下面是n位寄存器的代码,我们通过一个参数定义n,在实例化时传入参数n。
module regne (D, clk,Rst_n,E,Q); parameter n=4; input [n-1:0] D; input clk; input Rst_n; //复位信号 input E; //使能信号 output reg [n-1:0] Q; always @(posedge clk,negedge Rst_n) if(Rst_n==0) Q <= 0; else if(E) Q <= D; endmodule
`timescale 1ns/1ns `define clock_period 20 module regne_tb; reg [7:0] D; wire [7:0] Q; reg clk; reg Rst_n; reg E; regne #(.n(8)) regne(.D(D),.clk(clk),.Rst_n(Rst_n),.E(E),.Q(Q)); always # (`clock_period/2) clk = ~clk; initial begin D = 4'b01010101; clk = 1'b0; Rst_n = 1'b1; E = 1'b1; #(`clock_period) Rst_n = 1'b0; D = 4'b10101010; #(`clock_period*2) E = 1'b0; Rst_n = 1'b1; D = 4'b00010001; #(`clock_period*4) E = 1'b1; D = 4'b1111; #(`clock_period*2) D = 4'b10111011; #(`clock_period*2) D = 4'b10011001; #(`clock_period*2) $stop; end endmodule
下面的电路能实现带使能和异步复位的n位寄存器(这儿假设是4位)。D3D2D1D0是寄存器输入值。Q3Q2Q1Q0是寄存器输出值。
移位寄存器
寄存器移位可以实现整数乘法和触发,左移一位且在末位补0,相当于乘以2,右移一位可以实现除2功能。有移位功能的寄存器称作移位寄存器。
下面的电路可以实现把自身内容右移一位的4位移位寄存器:数据以串行的方式从输入端In移入移位寄存器,在时钟的上升沿每个触发器的内容传输到下一个触发器。假设初始状态为0,在连续的8个周期内输入信号In的值分别为: 1,0,1,1,1,0,0,0,则各个寄存器状态的变化如下表:
In | Q0 | Q1 | Q2 | Q3(out) | |
t0 | 1 | 0 | 0 | 0 | 0 |
t1 | 0 | 1 | 0 | 0 | 0 |
t2 | 1 | 0 | 1 | 0 | 0 |
t3 | 1 | 1 | 0 | 1 | 0 |
t4 | 1 | 1 | 1 | 0 | 1 |
t5 | 0 | 1 | 1 | 1 | 0 |
t6 | 0 | 0 | 1 | 1 | 1 |
t7 | 0 | 0 | 0 | 1 | 1 |
下面的代码实现把串行的输入存储到一个寄存器,可以选择时机并行输出。电路还带有一个Load信号,如果Load=1,则移位寄存器装入初始值,否则执行移位操作。这种串行加载并行读取数据电路叫串-并转化器。
/*串行输入,并行输出寄存器 从高位输入,即从右向左输入*/ module shiftn(R,L,w,clk,Q); parameter n=8; input [n-1:0] R;//初始值 input L; //load信号 input w; //移入信号 input clk;//时钟信号 output reg [n-1:0] Q; integer k; always @(posedge clk) begin if(L) Q <=R; else begin for(k=0; k<n-1; k=k+1) Q[k] <= Q[k+1]; Q[n-1] <= w; end end endmodule
`timescale 1ns/1ns `define clock_period 20 module shiftn_tb; reg [7:0] R; reg L; reg w; reg clk; wire [7:0] Q; shiftn #(.n(8)) shitn0(.R(R),.L(L),.w(w),.clk(clk),.Q(Q)); initial clk = 0; always #(`clock_period/2) clk = ~clk; initial begin R = 8'b00000000; L = 1'b1; w = 1'b0; #(`clock_period) L = 1'b0; w = 1'b1; #(`clock_period) w = 1'b0; #(`clock_period) w = 1'b1; #(`clock_period) w = 1'b1; #(`clock_period) w = 1'b1; #(`clock_period) w = 1'b1; #(`clock_period) w = 1'b1; #(`clock_period) w = 1'b1; #(`clock_period) $stop; end endmodule
我们也可以使用拼接符操作代替for循环,实现同样的功能,而且语法更加简单。
/*串行输入,并行输出寄存器 从高位输入,即从右向左输入*/ module shiftn(R,L,w,clk,Q); parameter n=8; input [n-1:0] R;//初始值 input L; //load信号 input w; //移入信号 input clk;//时钟信号 output reg [n-1:0] Q; always @(posedge clk) begin if(L) Q <=R; else begin Q = {w,Q[n-1:1]}; end end endmodule
下面的电路可以实现串行输入,并行输出;并行输入,串行输出;