复旦微试题(1)

群里看到的一道题目,可以用状态机的方法解决。

DILE:等待in信号拉高

s0 :计数in信号维持周期数

s1:小于4时的状态,out输出0,跳回IDLE

s2:大于4时的状态,out输出n/4个时钟周期,然后跳回IDLE


代码如下,用的三段式状态机,加强自己写三段式的熟练度和经验

module test(in,clk ,out , rst) ;
  input in , clk , rst ;
  output reg out ;
  
  reg [4:0] cnt ;
  reg [1:0] cstate , nstate , fin ;
  reg  inbuf , neg_in , pos_in  ;
  
   parameter IDLE = 0 ;
   parameter s0 = 1 ;
   parameter s1 = 2 ;
   parameter s2 = 3 ;
  module test(in,clk ,out , rst) ;
  input in , clk , rst ;
  output reg out ;
  
  reg [4:0] cnt ;
  reg [1:0] cstate , nstate , fin ;
  reg  inbuf , neg_in , pos_in  ;
  
   parameter IDLE = 0 ;
   parameter s0 = 1 ;
   parameter s1 = 2 ;
   parameter s2 = 3 ;
  
  always @(posedge clk  ) begin  //这一部分没有使用到
    inbuf <= in ;
    pos_in <= in & (~inbuf) ;
    neg_in <= (~in) & inbuf ;
  end
  
  
  always @(posedge clk or negedge rst ) begin
    if(~rst) cstate <= IDLE ;
    else cstate <= nstate ;
  end
   
   always@(clk ) begin
     nstate = IDLE ;
      case(cstate)
        IDLE: 
        if(in) nstate = s0 ;
        else nstate = IDLE ;
        s0 : begin
        if(in) nstate = s0 ;
        else if(cnt>=4) nstate = s2 ;
        else nstate = s1 ;
        end
        s1:
        nstate = IDLE ;
        s2 : begin
        if(cnt<4) nstate = IDLE ;
        else nstate = s2 ;
        end
        default : ;
     endcase
   end
     
     always@(posedge clk or negedge rst) begin
       if(~rst) begin
         cnt <= 0 ;
         fin <= 0 ;
         out <= 0 ;
       end
       case(nstate) 
         IDLE : begin
         out <= 0 ;
         cnt <= 0 ;
       end
         s0 : begin
              cnt <= cnt + 1 ;
          end
         s1 : begin
              out <= 0 ;
              cnt <= 0 ;
            end
         s2 : begin
              out <= 1 ;
              cnt <= cnt - 4 ;
          end
          default : ;
        endcase
      end
      
  endmodule      
          
        
  always @(posedge clk  ) begin
    inbuf <= in ;
    pos_in <= in & (~inbuf) ;
    neg_in <= (~in) & inbuf ;
  end
  
  
  always @(posedge clk or negedge rst ) begin
    if(~rst) cstate <= IDLE ;
    else cstate <= nstate ;
  end
   
   always@(clk ) begin
     nstate = IDLE ;
      case(cstate)
        IDLE: 
        if(in) nstate = s0 ;
        else nstate = IDLE ;
        s0 : begin
        if(in) nstate = s0 ;
        else if(cnt>=4) nstate = s2 ;
        else nstate = s1 ;
        end
        s1:
        nstate = IDLE ;
        s2 : begin
        if(cnt<4) nstate = IDLE ;
        else nstate = s2 ;
        end
        default : ;
     endcase
   end
     
     always@(posedge clk or negedge rst) begin
       if(~rst) begin
         cnt <= 0 ;
         fin <= 0 ;
         out <= 0 ;
       end
       case(nstate) 
         IDLE : begin
         out <= 0 ;
         cnt <= 0 ;
       end
         s0 : begin
              cnt <= cnt + 1 ;
          end
         s1 : begin
              out <= 0 ;
              cnt <= 0 ;
            end
         s2 : begin
              out <= 1 ;
              cnt <= cnt - 4 ;
          end
          default : ;
        endcase
      end
      
  endmodule
        
          
          


测试代码如下

`timescale 1ns/1ps 
module test_tb();
  reg clk , rst , in ;
  wire out ;
  
  initial begin
    clk = 0 ;
    rst = 0 ;
    in = 0 ;
    #100 rst = 1 ;
    #40 in = 1 ;
    #60 in = 0 ;
    #100 in = 1 ;
    #100 in = 0 ;
    #100 in = 1 ;
    #320 in = 0 ;
    #2000 $stop ;
  end
  
  test test_inst(
  .clk(clk) ,
  .in(in) ,
  .out(out) ,
  .rst(rst)
  );
  
  always #10 clk = ~clk ;
endmodule

代码10分钟,调试两小时。。。

 

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值