寄存器和移位寄存器,移位寄存器及其應用

移位寄存器(shift_reg)

在數字電路中,移位寄存器是一種在若幹相同時間脈衝下工作的以觸發器為基礎的器件,數據以並行或串行的方式輸入到該器件中,然後每個時間脈衝依次向左或右移動一個比特,在輸出端進行輸出。分為左移寄存器、右移寄存器和雙向移位寄存器三種。根據移位數據的輸入-輸出方式,又可將它分為串行輸入-串行輸出、串行輸入-並行輸出、並行輸入-串行輸出和並行輸入-並行輸出四種電路結構。
移位寄存器具有兩個特征:
(1)移位寄存器是由相同的寄存單元所組成。一般說來,寄存單元的個數就是移位寄存器的位數。為了完成不同的移位功能,每個寄存單元的輸出與其相鄰的下一個寄存單元的輸入之間的連接方式也不同。
(2)所有寄存單元共用一個時鍾。在公共時鍾的作用下,各個寄存單元的工作是同步的。每輸入一個時鍾脈衝,寄存器的就順序向左或向右移動一位。通常可按傳輸方式的不同對CMOS移位寄存器進行分類。移位寄存器的輸入方式有串行輸入和並行輸入之分。串行輸入就是在時鍾脈衝作用下,把要輸入的從一個輸入端依次一位一位地送入寄存器;並行輸入就是把輸入的從幾個輸入端同時送入寄存器。

使用串行輸入-串行輸出:
首先說明一種錯誤的寫法:盡管改變了data_in的值,但是data_reg[word_size-1:1]這三位由於是按照之前排列,所以data_in的值並不能通過寄存器傳遞至data_out,所以在vcs中data_out一直為0。

module shift#(parameter word_size=4)(input clk,input resetn,input data_in,output data_out);reg [word_size-1:0] data_reg;always@(posedge clk or negedge resetn)beginif(!resetn)data_reg<={word_size{1&#39;b0}};elsedata_reg<={data_reg[word_size-1:1],data_in};endassign data_out=data_reg[word_size-1];endmodule


一、下麵給出右移寄存器的正確寫法與tb文件

module shift#(parameter word_size=4)(input clk,input resetn,input data_in,output data_out);reg [word_size-1:0] data_reg;always@(posedge clk or negedge resetn)beginif(!resetn)data_reg<={word_size{1&#39;b0}};elsedata_reg<={data_in,data_reg[word_size-1:1]};endassign data_out=data_reg[0];endmodule module tb();reg data_in;reg clk;reg resetn;wire data_out;shift u1(.clk(clk),.resetn(resetn),.data_in(data_in),.data_out(data_out));initialbeginclk=0;forever #(20/2) clk=~clk;endinitialbeginresetn=0;#(2*20) resetn=1;endinitialbegin#40;#20 data_in=1;#20 data_in=0;endendmodule


二、左移寄存器的verilog代碼

module shift#(parameter word_size=4)(input clk,input resetn,input data_in,output data_out);reg [word_size-1:0] data_reg;always@(posedge clk or negedge resetn)beginif(!resetn)data_reg<={word_size{1&#39;b0}};elsedata_reg<={data_reg[word_size-2:0],data_in};endassign data_out=data_reg[word_size-1];endmodule


三、使用並行輸入,串行輸出

module shift#(parameter word_size=4)(input clk,input resetn,input [word_size-1:0] data_in,output data_out,input en);reg [word_size-1:0] data_reg;always@(posedge clk or negedge resetn)beginif(!resetn)data_reg<={word_size{1&#39;b0}};else if(en)data_reg<=data_in;elsedata_reg<={data_reg[0],data_reg[word_size-1:1]};endassign data_out=data_reg[0];endmodule module tb();reg [4-1:0] data_in;reg clk;reg en;reg resetn;wire data_out;shift u1(.clk(clk),.resetn(resetn),.data_in(data_in),.data_out(data_out),.en(en));initialbeginclk=0;forever #(20/2) clk=~clk;endinitialbeginresetn=0;#(2*20) resetn=1;en=1;data_in=4&#39;b1000;#20 en=0;endendmodule


四、使用串行輸入,並行輸出

module shift#(parameter word_size=4)(input clk,input resetn,input data_in,output [word_size-1:0] data_out,input en);reg [word_size-1:0] data_reg;always@(posedge clk or negedge resetn)beginif(!resetn)data_reg<={word_size{1&#39;b0}};else if(en)data_reg[0]<=data_in;elsedata_reg<={data_reg[0],data_reg[word_size-1:1]};endassign data_out=data_reg;endmodule

五、並行輸入,並行輸出

module shift #(parameter word_size=4)(input load,input clk,input rst_n,input [word_size-1:0] data_in,output reg [word_size-1:0] data_out);always@(posedge clk or negedge rst_n)beginif(!rst_n)data_out<=4&#39;b0000;else if(load)data_out<=data_in;endendmodule

根據以上的移位寄存器我們可以得出一個通用的移位寄存器:

module shift #(parameter word_size=4)(input clk,input rst_n,input [1:0] s,//modeinput [word_size-1:0] data_in,input MSB_in,// most significant bitinput LSB_in,// Least significant bitoutput reg [word_size-1:0] data_out,output MSB_out,output LSB_out);always@(posedge clk or negedge rst_n)beginif(!rst_n)data_out<=4&#39;b0000;elsebegincase(s)2&#39;b00:data_out<=data_out;2&#39;b01:data_out<={data_out[word_size-2:0],LSB_in}; //LSB2&#39;b10:data_out<={MSB_in,data_out[word_size-1:1]}; //MSB2&#39;b11:data_out<=data_in;endcaseendendassign MSB_out=data_out[word_size-1];assign LSB_out=data_out[0];endmodule module tb #(parameter word_size=4)();reg clk;reg rst_n;reg [1:0] s;reg [word_size-1:0] data_in;reg MSB_in;reg LSB_in;wire [word_size-1:0] data_out;wire MSB_out;wire LSB_out;shift u1(.clk(clk),.rst_n(rst_n),.s(s),.data_in(data_in),.MSB_in(MSB_in),.LSB_in(LSB_in),.data_out(data_out),.MSB_out(MSB_out),.LSB_out(LSB_out));initialbeginclk=0;forever #(20/2) clk=~clk;endtask rst(input [31:0]rst_time);beginrst_n=0;#rst_time rst_n=1;endendtaskinitialbeginrst(60);#40 s=01;LSB_in=1;#100 s=10;MSB_in=1;#100 s=11;data_in=4&#39;b1000;endendmodule