利用状态机的状态机实现层次结构化设计

FPGA/ASIC技术

190人已加入

描述

练习九.利用状态机的嵌套实现层次结构化设计目的:1.运用主状态机与子状态机产生层次化的逻辑设计;
 2.在结构化设计中灵活使用任务(task)结构。
在上一节,我们学习了如何使用状态机的实例。实际上,单个有限状态机控制整个逻辑电路的运转在实际设计中是不多见,往往是状态机套用状态机,从而形成树状的控制核心。这一点也与我们提倡的层次化、结构化的自顶而下的设计方法相符,下面我们就将提供一个这样的示例以供大家学习。
该例是一个简化的EPROM的串行写入器。事实上,它是一个EPROM读写器设计中实现写功能的部分经删节得到的,去除了EPROM的启动、结束和EPROM控制字的写入等功能,只具备这样一个雏形。工作的步骤是:1.地址的串行写入;2.数据的串行写入;3.给信号源应答,信号源给出下一个操作对象;4.结束写操作。通过移位令并行数据得以一位一位输出。
模块源代码:
module writing(reset,clk,address,data,sda,ack);
  input reset,clk;
  input[7:0] data,address;
  output sda,ack; //sda负责串行数据输出;
           //ack是一个对象操作完毕后,模块给出的应答信号。
  reg link_write; //link_write 决定何时输出。
  reg[3:0] state; //主状态机的状态字。
  reg[4:0] sh8out_state; //从状态机的状态字。
  reg[7:0] sh8out_buf;    //输入数据缓冲。
  reg finish_F;           //用以判断是否处理完一个操作对象。
  reg ack;
  parameter
    idle=0,addr_write=1,data_write=2,stop_ack=3;
  parameter
    bit0=1,bit1=2,bit2=3,bit3=4,bit4=5,bit5=6,bit6=7,bit7=8;
  assign   sda = link_write? sh8out_buf[7] : 1'bz;
  always @(posedge clk)
    begin
        if(!reset)               //复位。
          begin
             link_write<= 0;
             state    <= idle;
             finish_F <= 0;
             sh8out_state<=idle;
                   ack<= 0;
             sh8out_buf<=0;
          end
        else
          case(state)
          idle:                      
            begin
                link_write  <= 0;
               state    <= idle;
               finish_F <= 0;
               sh8out_state<=idle;
                     ack<= 0;
               sh8out_buf<=address; 
              state    <= addr_write;
            end
          addr_write:         //地址的输入。
            begin
                if(finish_F==0)
                  begin  shift8_out; end
                else
                  begin
                     sh8out_state <= idle;
                     sh8out_buf   <= data;
                            state <= data_write;
                         finish_F <= 0;
                  end
            end
          data_write:       //数据的写入。
            begin
                if(finish_F==0)
                  begin  shift8_out; end
                else
                  begin
                      link_write <= 0;
                           state <= stop_ack;
                        finish_F <= 0; 
                             ack <= 1;
                  end
            end    
          stop_ack:             //完成应答。
            begin
                  ack <= 0;
              state <= idle;
            end
         
          endcase      
    end                          
task shift8_out;                //串行写入。
  begin
     case(sh8out_state)
     idle:
       begin
           link_write  <= 1;
          sh8out_state <= bit0;
        end
     bit0:
       begin
           link_write <= 1;
         sh8out_state <= bit1;                                
           sh8out_buf <= sh8out_buf<<1;
       end
     bit1:
       begin
         sh8out_state<=bit2;
         sh8out_buf<=sh8out_buf<<1;
       end
     bit2:
       begin
         sh8out_state<=bit3;
         sh8out_buf<=sh8out_buf<<1;
       end
     bit3:
       begin
         sh8out_state<=bit4;
         sh8out_buf<=sh8out_buf<<1;
       end
     bit4:
       begin
         sh8out_state<=bit5;
         sh8out_buf<=sh8out_buf<<1;
       end
    
     bit5:
       begin
         sh8out_state<=bit6;
         sh8out_buf<=sh8out_buf<<1;
       end
     bit6:
       begin
         sh8out_state<=bit7;
         sh8out_buf<=sh8out_buf<<1;
       end
     bit7:
       begin
         link_write<= 0;
         finish_F<=finish_F+1;                               
       end 
      
     endcase
  end
endtask
endmodule         
测试模块源代码:
`timescale 1ns/100ps
`define clk_cycle 50
module writingTop;
  reg reset,clk;
  reg[7:0] data,address;
  wire ack,sda;
  always #`clk_cycle  clk = ~clk;
  initial
    begin
            clk=0;
            reset=1;
            data=0;
            address=0;
            #(2*`clk_cycle) reset=0;
            #(2*`clk_cycle) reset=1;
       #(100*`clk_cycle) $stop;
    end
  always @(posedge ack)      //接收到应答信号后,给出下一个处理对象。
    begin
            data=data+1;
            address=address+1;
    end        
  writing writing(.reset(reset),.clk(clk),.data(data),
                  .address(address),.ack(ack),.sda(sda)); 
endmodule       
仿真波形:[[wysiwyg_imageupload:252:height=174,width=496]]
练习:仿照上例,编写一个实现EPROM内数据串行读取的模块。编写测试模块,给出仿真波形。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分