fpga基于sc16c654的localbus实现

注意看这个时序是没有clk的,这是因为localbus是解复用的,地址和数据线是同步传过来的所以不需要再由clk进行同步,知道了这个,在针对性的去写就很容易了。这是根据sc16c654进行模拟设计,所以可以这样陈旭如下:

module sc16c654(

 input           SYS_CLK             , // (i) System Clock.     
    input           SYS_RST             , // (i) System Reset (high active)          
    //                                  
    input   [2:0]  addr        , // (i) 三位地址对应相应寄存器
    inout   [7:0]  date         , // (io)数据
    
    input     CS_a      , // (i) 片选a
    input     CS_b      , // (i) 片选b
    input     CS_c      , // (i) 片选c
    input     CS_d      , // (i) 片选d
    
    input           lor     , // (i) 读使能低有效
    input           low        // (i) 写使能低有效


);


//打拍后续进行下降沿检测//ddf
    reg   CS_a_dff    ;   
    reg   CS_b_dff    ;        
    reg   CS_c_dff    ;        
    reg   CS_d_dff    ;        
    reg     [2:0]       addr_dff           ;  
    reg     [7:0]       date_dff           ;
    reg                 low_dff            ;
 
 ddf1
 
    reg   CS_a_dff_1;
    reg   CS_b_dff_1 ;
    reg   CS_c_dff_1 ;
    reg   CS_d_dff_1 ;        
    reg     [2:0]         addr_dff_1        ;
    reg     [7:0]         date_dff_1        ;
    reg                   low_dff_1         ;
    
    reg             CS_a_dff_2         ;
    reg               CS_b_dff_2 ;
    reg               CS_c_dff_2 ;
    reg               CS_d_dff_2 ;    
    reg             low_dff_2        ;
    
 //下降沿标志信号   
    wire            s_CS_a_F            ;  //cs下降沿标志
    wire            s_CS_b_F            ;  //cs下降沿标志
    wire            s_CS_c_F            ;  //cs下降沿标志
    wire            s_CS_d_F            ;  //cs下降沿标志
    
    wire            s_WR_N_F            ;  //wr下降沿标志
    reg             r_WR_N_F            ;  //转变为寄存器形
    
    
    //读相关
    wire    [7:0]  s_RD_D              ;
    reg     [7:0]  r_RD_D              ;
    
    //***************************
    //sc16c654 write reg
    //初值
    //3'b000:                             //初值//PHR==xx OR THR==xx OR DLL==xx
    //3'b001:                                //LER==00 OR DLM==xx                
    //3'b010:                                //FCR==00 OR ISR==01  OR EFR==00    
    //3'b011:                               //LCR==00                           
    //3'b100:                             //MCR==00                                              
    //***************************
    
    reg [7:0]phr;
    reg [7:0]thr;
    reg [7:0]dll;
    reg [7:0]ler;
    reg [7:0]dlm;
    
    reg [7:0]fcr;
    reg [7:0]lsr;
    reg [7:0]efr;
    reg [7:0]lcr;
    reg [7:0]mcr;
    
    //dff1
    always @ (posedge SYS_CLK or posedge SYS_RST) begin
        if (SYS_RST) begin
            
            CS_a_dff <= 1'b1    ;   
            CS_b_dff <= 1'b1    ;        
            CS_c_dff <= 1'b1    ;        
            CS_d_dff <= 1'b1   ;        
            addr_dff <= 3'b0;   ;  
            date_dff <= 8'b0;  ;
            low_dff  <= 1'b1;   ;
            
            
        end
        else begin
        
            CS_a_dff <= CS_a   ;
            CS_b_dff <= CS_b    ;    
            CS_c_dff <= CS_c    ;    
            CS_d_dff <= CS_d    ;   
            addr_dff <= addr;   ;  
            date_dff <= date;  ;
            low_dff  <= low;   ;
            
        end
    end
    
    //dff2
   always @ (posedge SYS_CLK or posedge SYS_RST) begin
        if (SYS_RST) begin
            
            CS_a_dff_1 <= 1'b1    ;   
            CS_b_dff_1 <= 1'b1    ;        
            CS_c_dff_1 <= 1'b1    ;        
            CS_d_dff_1 <= 1'b1   ;        
            addr_dff_1 <= 3'b0   ;  
            date_dff_1 <= 8'b0 ;
            low_dff_1  <= 1'b1   ;
            
            
        end
        else begin
        
            CS_a_dff_1 <= CS_a_dff  ;
            CS_b_dff_1 <= CS_b_dff   ;    
            CS_c_dff_1 <= CS_c_dff   ;    
            CS_d_dff_1 <= CS_d_dff   ;   
            addr_dff_1 <= addr_dff   ;  
            date_dff_1 <= date_dff  ;
            low_dff_1  <= low_dff   ;
            
        end
    end
    
    //
    always @ (posedge SYS_CLK or posedge SYS_RST) begin
        if (SYS_RST) begin
        
            CS_a_dff_2 <= 1'b1   ;  
            CS_b_dff_2 <= 1'b1   ;  
            CS_c_dff_2 <= 1'b1   ;
            CS_d_dff_2 <= 1'b1   ;  
            low_dff_2  <= 1'b1   ;
            
        end
        else begin
            
            CS_a_dff_2 <=CS_a_dff_1    ;  
            CS_b_dff_2 <=CS_b_dff_1    ;  
            CS_c_dff_2 <=CS_c_dff_1   ;
            CS_d_dff_2 <=CS_d_dff_1   ;
            low_dff_2  <=low_dff_1    ;
            
            
            
        end
    end
    
    assign s_CS_a_F = (CS_a_dff_1 == 1'b0 && CS_a_dff_2 == 1'b1) ? 1'b1 : 1'b0;
    assign s_CS_b_F = (CS_b_dff_1 == 1'b0 && CS_b_dff_2 == 1'b1) ? 1'b1 : 1'b0;
    assign s_CS_c_F = (CS_c_dff_1 == 1'b0 && CS_c_dff_2 == 1'b1) ? 1'b1 : 1'b0;
    assign s_CS_d_F = (CS_d_dff_1 == 1'b0 && CS_d_dff_2 == 1'b1) ? 1'b1 : 1'b0;
    
    assign s_WR_N_F = (low_dff_1 == 1'b0 && low_dff_2 == 1'b1) ? 1'b1 : 1'b0;
    
    //对wr低有效标志位进一步寄存
     always @ (posedge SYS_CLK or posedge SYS_RST) begin
        if (SYS_RST) begin
            r_WR_N_F <= 1'b0;
        end else begin
            r_WR_N_F <= s_WR_N_F;
        end
    end  
    
    
    always @ (posedge SYS_CLK or posedge SYS_RST) begin
        if (SYS_RST) begin
            phr<=2'hz;
            thr<=2'hz;
            dll<=2'hz;
            ler<=2'h00;
            dlm<=2'hz;
            
            fcr<=2'h00;
            lsr<=2'h01;
            efr<=2'h00;
            lcr<=2'h00;
            mcr<=2'h00;
            
            
         end
         else begin
            if (r_WR_N_F == 1'b1 && s_CS_a_F == 1'b0) begin
                case (addr_dff_1)
                    3'b000           :   begin        
                                            phr <= date_dff_1 ;
                                        end         
                    3'b001          :   begin       
                                            thr <= date_dff_1 ;
                                        end         
                    3'b010          :   begin       
                                            dll <= date_dff_1 ;
                                        end         
                    3'b011           :   begin       
                                            ler <= date_dff_1 ;
                                        end         
                endcase
                end
                end
end

 assign s_RD_D =     (addr_dff == 3'b000 ) ? phr  :
                     (addr_dff == 3'b001) ? thr  :
                     (addr_dff == 3'b010) ? dll  :
                     (addr_dff == 3'b011) ? ler  :8'b0;
                    


always @ (posedge SYS_CLK or posedge SYS_RST) begin
        if (SYS_RST) begin
            r_RD_D <= 8'b0;
        end else begin
            if (s_CS_a_F == 1'b1) begin
                r_RD_D <= s_RD_D;
            end
        end
    end                                   
    
    assign date = (CS_a_dff_2 == 1'b0 && lor == 1'b0) ? r_RD_D     : 8'bzzzzzzzz;  
    assign date = (CS_b_dff_2 == 1'b0 && lor == 1'b0) ? r_RD_D     : 8'bzzzzzzzz;  
    assign date = (CS_c_dff_2 == 1'b0 && lor == 1'b0) ? r_RD_D     : 8'bzzzzzzzz;  
    assign date = (CS_d_dff_2 == 1'b0 && lor == 1'b0) ? r_RD_D     : 8'bzzzzzzzz;  

endmodule

tb文件:

module sc1654_tb();
reg           SYS_CLK ;             // (i) System Clock.     
    reg           SYS_RST ;             // (i) System Reset (high active)          
    //                                  
    reg   [2:0]   addr ;        // (i) 三位地址对应相应寄存器
    wire  [7:0]  date  ;        // (io)数据
    
    reg     CS_a     ; // (i) 片选a
    reg     CS_b     ; // (i) 片选b
    reg     CS_c     ; // (i) 片选c
    reg     CS_d     ; // (i) 片选d
    
    reg     lor     ; // (i) 读使能低有效
    reg     low     ;   // (i) 写使能低有效


 sc16c654  test(

    . SYS_CLK(SYS_CLK),             // (i) System Clock.     
    . SYS_RST(SYS_RST),             // (i) System Reset (high active)          
                         
    . addr(addr ) ,                  // (i) 三位地址对应相应寄存器
    . date( date) ,                 // (io)数据
         
    . CS_a(CS_a ) ,                 // (i) 片选a
    . CS_b(CS_b ) ,                 // (i) 片选b
    . CS_c(CS_c ) ,                 // (i) 片选c
    . CS_d(CS_d ) ,                 // (i) 片选d
          
    . lor (lor ) ,                     // (i) 读使能低有效
    . low (low )                    // (i) 写使能低有效

);


always #10 SYS_CLK = ~SYS_CLK;
    
    initial begin
        SYS_CLK = 1;
        SYS_RST = 1;
    
        addr =3'b111;        
        force date= 8'b0000_0000;

        CS_a = 1'b1   ;
        CS_b = 1'b1   ;
        CS_c = 1'b1   ;
        CS_d = 1'b1   ;
                  
        lor  = 1'b1  ;
        low  = 1'b1  ;


        //第一次写
        SYS_RST = 0;
        addr=3'b001;
        force date= 8'b1010_1010;
        CS_a = 1'b0   ;#21
        low  = 1'b0  ; #31
        CS_a = 1'b1   ;#31
        low  = 1'b1  ; #21
        //读
        addr=3'b001;
        CS_a = 1'b0   ;#21
        lor  = 1'b0  ; #31
        CS_a = 1'b1   ;#21
        lor  = 1'b1  ; #31
    
    
    
        //第二次写
        SYS_RST = 0;
        addr=3'b010;
        force date= 8'b1100_0011;
        CS_a = 1'b0   ;#21
        low  = 1'b0  ; #31
        CS_a = 1'b1   ;#31
        low  = 1'b1  ; #21
        //读
        addr=3'b010;
        CS_a = 1'b0   ;#21
        lor  = 1'b0  ; #31
        CS_a = 1'b1   ;#21
        lor  = 1'b1  ; #31

        #2000;
        $stop;
end
endmodule

仿真图如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值