05状态机实现八位移位寄存器与验证
一是设计功能:
在程序中设计了8位的移位寄存器,在Idle状态下,判断shift_start信号是否为高,如果为高,进入Start状态,在Start状态延迟100个周期,进入Run状态,进行移位处理,如果shift_stop信号有效了,进入Stop状态,在Stop状态,清零q的值,再跳转到Idle状态。
二是设计输入:
module shift_8 ( input shift_start, input shift_stop, input rst_n, input clk, input d, output reg [7:0] q ); parameter Idle = 2\’d0 ; //Idle state parameter Start = 2\’d1 ; //Start state parameter Run = 2\’d2 ; //Run state parameter Stop = 2\’d3 ; //Stop state reg [1:0] current_state ; //statement reg [1:0] next_state ; //statement reg [6:0] delay_cnt ; //delay counter
always@(posedge clk or negedge rst_n) if(!rst_n) current_state<=Idle; else current_state<=next_state;
always@(*) begin case(current_state) Idle: begin if(shift_start) next_state<=Start; else next_state<=Idle; end
Start: begin if(delay_cnt==7\’d99) next_state<=Run; else next_state<=Start; end
Run: begin if(shift_stop) next_state<=Stop; else next_state<=Run; end
Stop: begin next_state<=Idle; end default:next_state<=Idle; endcase end
//count to 99,timer,,delay_cnt module
// current_state==Start,条件是当前状态是多少,输出多少 always@(posedge clk or negedge rst_n) if(!rst_n) delay_cnt<=7\’d0; else if(current_state==Start) delay_cnt<=delay_cnt+1\’b1;
else delay_cnt<=7\’d0;
// current_state==Start,条件是当前状态是多少,输出多少 always@(posedge clk or negedge rst_n) if(!rst_n) q<=8\’d0; else if(current_state==Run) q<={q[6:0],d};
else q<=8\’d0;
endmodule |
设计方法是三段式状态机,且移位方式有两种,位移运算符<<和位拼接符,本设计采用后者。
- 三段式:用三个always模块来描述状态机。其中一个模块采用同步时序逻辑电路描述状态转移,另一个模块采用组合逻辑判断状态转移条件(注意和两段式的区别)。第三个模块描述状态的输出(既可以用组合逻辑也可以用时序逻辑)
下面是testbench仿真设计代码:
//第一行为时间尺度预处理指令,(设置)时间单位与时间精度 //attion.. `timescale 1ns/1ns //激励文件的名称 module shift_8_tb(); //下面为激励文件的信号的定义
reg shift_start ; reg shift_stop ; reg rst ; reg clk ; reg d ; //注意点:输入定义为reg,,寄存器型,输出定义为wire wire [7:0] q ; // shift_8 shift_8i ( // port map – connection between master ports and signals/registers .clk(clk), .d(d), .q(q), .rst_n(rst), .shift_start(shift_start), .shift_stop(shift_stop) );
//激励文件的例化,设置激励的初始值,其他值(其他情况) //$random(seed),随机数产生函数,seed是参数值 initial begin rst = 0 ; clk = 0 ; d = 0 ; #20 rst = 1 ; forever begin #({$random}%100) d = ~d ; end end
initial begin shift_start = 0 ; shift_stop = 0 ; #300 shift_start = 1 ; #2020 shift_start = 0 ; #2000 shift_stop = 1 ; #50 shift_stop = 0 ; $stop; end
always #10 clk = ~clk ;
endmodule
|
仿真代码解释: 随机延时0-99ns后,通过调用随机函数$random产生这个延时,再取反一位的移位值。通过(shift_start维持高电平超过100个周期)延时足够的100个时钟周期进入run状态(进行移位操作)在run状态保持一段时间,进入stop状态,仿真结束。
仿真波形如下:
总结:通过今天这个8位移位寄存器的设计:收获有两个,一是三段式状态机:时序逻辑描述状态转移,组合逻辑判断状态转移条件,描述状态的输出。
二是移位操作:位拼接符实现。q<={q[6:0],d};或po_a <= {po_a[6:0],po_a[7]};
移位运算符:po_a <= po_a<<1;(注意多一个:
else if(po_a == 8\’b1000_0000)
po_a <= 8\’b0000_0001;
)