Xilinx FPGA:vivado关于真双端口的串口传输数据的实验

一、实验内容

用一个真双端RAM,端口A和端口B同时向RAM里写入数据0-99,A端口读出单数并存入单端口RAM1中,B端口读出双数并存入但端口RAM2中,当检测到按键1到来时将RAM1中的单数读出显示到PC端,当检测到按键2到来时,将RAM2中的双数显示到pc端。

二、信号流向图

TIPS:这里我本来想将single_ram_1和single_ram_2分成两个单独的模块,但是经过实验后发现,如果分成两个单独的模块的话会导致:

①两个单端RAM模块的tx_start(0或1)都会有值给uart_tx模块,即使是RAM1给【1】,RAM2中没有值【0】,uart_tx模块是无法判断 tx_start 到底来自于哪个模块,所以此时uart_tx模块只是能接收到一个tx_start的脉冲信号,但是无法判断信号来自哪个RAM模块,无法获取到相应的uart_data ,最终导致tx_flag都无法变成高电平,那就更不会返回给RAM模块tx_done信号了。

②如果单独为了正确信号能赋值给tx_start而重新去写一个ctrl模块的话,那么在ctrl模块中将无法使用判断条件,因为我们将状态作为了赋值条件而不仅仅是key_flag信号。

那么我的解决方法就是把single_ram_2例化到single_ram_1当中,将single_ram_2输出的数据(uart_data_b及tx_start_b)和single_ram_1输出的数据(douta即tx_start_a)全部放在一个模块即single_ram_1中去做判断,但是我们仍然无法将single_ram_2的状态作为赋值的条件,所以只能采用这种比较粗暴的方式,也就是除了( cur_state == REG || cur_state == READ )时候tx_start <= tx_start_a ;那么其他情况就是tx_start <= tx_start_b ; uart_data的处理也是同样。详见后面程序。

其实最好的方式是将single_ram_2和single_ram_1写在同一个模块中,程序放在文章最后了。

三、程序设计

(1)按键消抖模块:

这里注意key1和key2不能使用同一个计数器,不然在同一个模块中也会判断出问题。

Matlab 复制代码
`timescale 1ns / 1ps
module key_debounce(
  input           sys_clk    ,
  input           rst_n      ,
  input           key1        ,
  input           key2        ,
  output          key_flag_1   ,
  output          key_flag_2
    );
//    parameter              delay = 100_000_0   ; //20ms
    parameter              delay = 100;// 测试用
    reg[19:0]               cnt1   ;
    reg[19:0]               cnt2   ;
  
  key_flag_1  
    always@(posedge sys_clk )
         if(!rst_n)
            cnt1 <= 0 ;
         else if ( key1 == 0 )begin
              if ( cnt1 == delay -1 )
                   cnt1 <= cnt1 ;
              else 
                   cnt1 <= cnt1 +1 ;
         end
         else
         cnt1 <= 0 ;
     
     assign  key_flag_1 = ( cnt1 == delay -2 )?1:0 ;
   
   ///key_flag_2
     always@(posedge sys_clk )
         if(!rst_n)
            cnt2 <= 0 ;
         else if ( key2 == 0 )begin
              if ( cnt2 == delay -1 )
                   cnt2 <= cnt2 ;
              else 
                   cnt2 <= cnt2 +1 ;
         end
         else
         cnt2 <= 0 ;
     
     assign  key_flag_2 = ( cnt2 == delay -2 )?1:0 ;  
    
 
    
    
endmodule

(2)真双端模块:

IP参数:

Matlab 复制代码
`timescale 1ns / 1ps
module the_true_ram(
     input                 sys_clk     ,
     input                 rst_n       ,
     output  [7:0]         ram_odd_data  ,
     output  [7:0]         ram_even_data
    );
    A端口
    reg          wea     ;
    reg  [6 : 0] addra   ;
    reg  [7 : 0] dina    ;
    wire [7 : 0] douta   ;
    
    always@(posedge sys_clk )
         if(!rst_n)
            wea <= 0 ;
         else if ( addra >= 99 )
            wea <= 0 ;
         else
            wea <= 1 ;
    
    always@(posedge sys_clk )
         if(!rst_n)
            addra <= 0 ;
         else if ( addra >= 99 )
            addra <= 99 ;
         else
            addra <= addra +1 ;
    
    always@(posedge sys_clk )
         if(!rst_n)
            dina <= 0 ;
         else if (dina >= 99)
            dina <= 99 ;
         else
            dina <= dina +1 ;
    
    wire [7:0]        data_a  ;
    assign       data_a = douta ;
    assign       ram_odd_data = (data_a%2 == 1)?data_a : ram_odd_data ;
      
    ///b端口
     reg          web    ; 
     reg  [6 : 0] addrb  ;
     reg  [7 : 0] dinb   ;
     wire [7 : 0] doutb  ;
     
     always@(posedge sys_clk )
          if(!rst_n)
             web <= 0 ;
          else if ( addrb >= 99 )
             web <= 0 ;
          else
             web <= 1 ;
   
   always@(posedge sys_clk )
        if(!rst_n)
           addrb <= 0 ;
        else if ( addrb >= 99 )
           addrb <= 99 ;
        else
           addrb <= addrb +1 ;
    
    always@(posedge sys_clk )
         if(!rst_n)
            dinb <= 0 ;
         else if ( dinb >= 99 )
            dinb <= 99 ;
         else
            dinb <= dinb +1 ;
  
    wire[7:0]   data_b  ;
    assign      data_b = doutb ;
    assign      ram_even_data = (data_b %2 == 0 )? data_b : ram_even_data ;
    
    
    
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
true_ram your_instance_name (
  .clka(sys_clk ),    // input wire clka
  .ena(1),      // input wire ena
  .wea(wea),      // input wire [0 : 0] wea
  .addra(addra),  // input wire [6 : 0] addra
  .dina(dina),    // input wire [7 : 0] dina
  .douta(douta),  // output wire [7 : 0] douta
  .clkb(sys_clk ),    // input wire clkb
  .enb(1),      // input wire enb
  .web(web),      // input wire [0 : 0] web
  .addrb(addrb),  // input wire [6 : 0] addrb
  .dinb(dinb),    // input wire [7 : 0] dinb
  .doutb(doutb)  // output wire [7 : 0] doutb
);
// INST_TAG_END ------ End INSTANTIATION Template ---------





endmodule

(3)单端RAM2模块:

但其实深度在50就够用了。(100里面的奇数和偶数50)

Matlab 复制代码
`timescale 1ns / 1ps
module single_ram_2_FMS(
   input               sys_clk        ,
   input               rst_n          ,
   input               key_flag_2     ,
   input               tx_done        ,
   input    [7:0]      ram_even_data  ,
   output   reg        tx_start_b       ,
   output   reg[7:0]   uart_data_b

    );
    存双数的RAM
    reg          ena           ;
    reg  [0 : 0] wea           ;
    reg  [6 : 0] addra         ;
    reg  [7 : 0] dina          ;
    wire [7 : 0] douta         ;

    //先写再读出
    localparam         IDLE  = 3'd0 ;
    localparam         WRITE = 3'd1 ;
    localparam         REG   = 3'd2 ;
    localparam         READ  = 3'd3 ;
    
    reg[2:0]           cur_state    ;
    reg[2:0]           next_state   ;

    
    //state1
    always@(posedge sys_clk )
         if(!rst_n)
            cur_state <= IDLE ;
         else 
            cur_state <= next_state ;
    
    //state2
    always@(*)
          case(cur_state)
              IDLE  :
                     begin
                         next_state = WRITE ;
                     end
              WRITE :
                     begin
                        if ( key_flag_2 )
                            next_state = REG ;
                        else
                            next_state = cur_state ;
                     end
              REG   :
                     begin
                         next_state = READ ;
                     end
              READ  :
                     begin
                         if(addra == 49)
                            next_state = IDLE ;
                         else
                            next_state <= cur_state ;
                     end
          default:;
          endcase
   
   //state3
   always@(posedge sys_clk )
        if(!rst_n)begin
           ena   <= 0 ;
           wea   <= 0 ;
           addra <= 0 ;
           dina  <= 0 ;
           tx_start_b <= 0 ;
        end
        else
            case(cur_state)
                  IDLE   :
                          begin
                               ena   <= 0 ;
                               wea   <= 0 ;
                               addra <= 0 ;
                               dina  <= ram_even_data ;
                          end
                  WRITE  :
                          begin
                              ena <= 1 ;
                              wea <= 1 ;
                              if(addra == 49)
                                 addra <= 49 ;
                              else
                                 addra <= addra +1 ;
                              dina <= ram_even_data ;
                          end
                  REG    :
                          begin
                              addra <= 0 ;
                              ena   <= 0 ;
                              wea   <= 0 ;
                              dina  <= 0 ;
                              tx_start_b <= 1 ;
                          end
                  READ   :
                          begin
                              ena <= 1 ;
                              wea <= 0 ;
                              dina<= 0 ;
                              if(tx_done)begin
                                 tx_start_b <= 1 ;
                                 addra <= addra +1 ;
                              end
                              else begin
                                 tx_start_b <= 0 ;
                                 addra <= addra ;
                                 end
                          end
            default:;
            endcase
           
    
    
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
single_ram ram2 (
  .clka(sys_clk ),    // input wire clka
  .ena(ena),      // input wire ena
  .wea(wea),      // input wire [0 : 0] wea
  .addra(addra),  // input wire [6 : 0] addra
  .dina(dina),    // input wire [7 : 0] dina 
  .douta(douta)  // output wire [7 : 0] douta
);
// INST_TAG_END ------ End INSTANTIATION Template ---------
    
    always@(posedge sys_clk )
         if(!rst_n)
            uart_data_b <= 0 ;
         else if ( cur_state == READ )
            uart_data_b <= douta ;
         else
            uart_data_b <= uart_data_b ;
    

  always@(posedge sys_clk )
       if(!rst_n)
          tx_start_b <= 0 ;
       else if ( cur_state == REG || cur_state == READ  )
           tx_start_b <= 1 ;
       else
          tx_start_b <= tx_start_b ;  
    
    
endmodule

(4)单端RAM1模块

配置和前面一样

Matlab 复制代码
`timescale 1ns / 1ps
module single_ram_1_FMS(
    input                 sys_clk      ,
    input                 rst_n        ,
    input                 key_flag_1   ,
    input                 key_flag_2   ,
    input                 tx_done      ,
    input[7:0]            ram_odd_data ,
    input[7:0]            ram_even_data,
    output      reg       tx_start     ,
    output   reg[7:0]     uart_data        
 
    );
    /读单数的RAM
    reg          ena     ;       
    reg          wea     ;
    reg  [6 : 0] addra   ;
    reg  [7 : 0] dina    ;
    wire [7 : 0] douta   ;
    
    reg           tx_start_a  ;
   wire           tx_start_b     ; 
   wire[7:0]      uart_data_b    ; 

    
   先写再读出
   localparam             IDLE   = 3'd0 ;
   localparam             ERITE  = 3'd1 ;
   localparam             REG    = 3'd2 ;
   localparam             READ   = 3'd3 ;
   
   reg[2:0]        cur_state    ;
   reg[2:0]        next_state   ;

   
   //state1
   always@(posedge sys_clk )
        if(!rst_n)
           cur_state <= IDLE  ;
        else
           cur_state <= next_state ;
   
   //state2
   always@(*)
        case(cur_state)
            IDLE  :
                   begin
                       next_state = ERITE ;
                   end
            ERITE :
                   begin
                       if(key_flag_1)
                          next_state = REG ;
                       else
                          next_state <= cur_state ;
                   end
            REG   :
                   begin
                       next_state = READ ;//用来发送tx_start
                   end
            READ  :
                   begin
                       if(addra == 49)//100内的单数是50
                         next_state = IDLE ;
                       else
                         next_state = cur_state ;
                   end
        default:;
        endcase
    
    //state3
    always@(posedge sys_clk )
         if(!rst_n)begin
               ena  <= 0 ;
               wea  <= 0 ;
               addra<= 127 ;
               dina <= 0 ;
               tx_start_a <= 0 ;
         end
         else
             case(cur_state)
                     IDLE  :
                            begin
                                 ena  <= 0 ;
                                 wea  <= 0 ;
                                 addra<= 7'd127 ;
                                 dina <= ram_odd_data ;
                            end
                     ERITE :
                            begin
                                ena <= ~ena ;
                                wea <= ~wea ;
                                if( addra == 49 && wea)
                                    addra <= 49 ;
                                else if(wea)
                                    addra <= addra +1 ;
                                    dina <= ram_odd_data ;
                            end
                     REG   :
                            begin
                                ena  <= 0 ;         
                                wea  <= 0 ;         
                                addra<= 0 ;         
                                dina <= 0 ;   
                                tx_start_a <= 1 ;                            
                            end
                     READ  :
                            begin
                                 ena <= 1 ;
                                 wea <= 0 ;
                                 dina<= 0 ;
                                 if(tx_done)begin
                                    tx_start_a <= 1 ;
                                    addra <= addra +1 ;
                                 end
                                 else begin
                                    tx_start_a <= 0 ;
                                    addra <= addra ;
                                    end
                            end
             default:;
             endcase

    
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
single_ram ram1 (
  .clka(sys_clk ),    // input wire clka
  .ena(ena),      // input wire ena
  .wea(wea),      // input wire [0 : 0] wea
  .addra(addra),  // input wire [6 : 0] addra
  .dina(dina),    // input wire [7 : 0] dina
  .douta(douta)  // output wire [7 : 0] douta
);
// INST_TAG_END ------ End INSTANTIATION Template ---------
    
 
  always@(posedge sys_clk )
       if(!rst_n)
          uart_data <= 0;
       else if ( cur_state == READ )
          uart_data <= douta ;
       else
          uart_data <= uart_data_b ;
          
  

  always@(posedge sys_clk )
       if(!rst_n)
          tx_start <= 0 ;
       else if ( cur_state == REG || cur_state == READ  )
          tx_start <= tx_start_a ;
       else
          tx_start <= tx_start_b ; 
  
  
  例化ram2 



   
 single_ram_2_FMS  single_ram_2_FMS_u(
                                 .  sys_clk       (sys_clk      )    ,
                                 .  rst_n         (rst_n        )    ,
                                 .  key_flag_2    (key_flag_2   )    ,
                                 .  tx_done       (tx_done      )    ,
                                 .  ram_even_data (ram_even_data)    ,
                                 .  tx_start_b    (tx_start_b   )    ,
                                 .  uart_data_b   (uart_data_b  )

    );   
    
    
    
    
    
    
    
    
endmodule

(5)uart_tx模块:

Matlab 复制代码
`timescale 1ns / 1ps
module uart_tx(
     input               sys_clk   ,
     input               rst_n     ,
     input  wire[7:0]   uart_data ,
     input               rx_done   ,        
     output   reg        tx_data   , 
     output   reg        tx_done
    );
    parameter         SYSCLK =   50_000_000  ;
    parameter         Baud   =   115200      ;
    parameter         COUNT  =   SYSCLK/Baud ;//434   传输1比特所需要的时钟周期
    parameter         MID    =   COUNT/2     ;
 
    wire                 start_flag ;
    reg                  tx_flag   ;
 
    reg                  tx_reg1   ;
    reg                  tx_reg2   ;
    
    reg[4:0]             cnt_bit   ;
    reg[10:0]            cnt       ;
 
 
 
//tx_start
    always@(posedge sys_clk)
          if(!rst_n)begin
             tx_reg1 <= 0 ;
             tx_reg2 <= 0 ;
           end
           else begin
              tx_reg1 <= rx_done  ;
              tx_reg2 <= tx_reg1  ;
           end
 
   assign  start_flag = tx_reg1 & ~tx_reg2 ;
 
 ///tx_flag
   always@(posedge sys_clk)
         if(!rst_n)
            tx_flag <= 0 ;
         else if ( start_flag == 1 )
            tx_flag <= 1 ;
         else if ( cnt == COUNT -1 && cnt_bit == 10)
//         else if ( cnt == MID -1 && cnt_bit == 10)
            tx_flag <= 0 ;
         else
            tx_flag <= tx_flag ;
 ///计时器
  //    cnt 434  
     always@(posedge sys_clk )
           if(!rst_n)
              cnt <= 0;
           else if ( tx_flag == 1 )begin
                if ( cnt == COUNT -1) ///一定要减一,如果不减一,实际会计到435次,反算回去波特率就不是115200了
                    cnt <= 0;
                else
                    cnt <= cnt +1 ;
           end
           else
               cnt <= 0 ;
  
   //  /计数器
      always@(posedge sys_clk )
           if(!rst_n)
              cnt_bit <= 0 ;
           else if ( tx_flag )begin
                if ( cnt == COUNT -1)begin
                    if(cnt_bit == 10)///0123456789 10
                    cnt_bit <= 0 ;
                    else
                    cnt_bit <= cnt_bit +1 ;
                    end
                else
                cnt_bit <= cnt_bit     ;
                end
           else
           cnt_bit <= 0 ;
           
  parameter             MODE_CHECK = 0 ;
 

     always@(posedge sys_clk )
          if(!rst_n)
          tx_data <= 1 ;   //表示没有数据
          else if ( tx_flag )begin
                if (   cnt_bit > 0 && cnt_bit < 9 )
                ///cnt_bit 0 12345678 9 
                ///tx_data 0123456789
                ///uart_data 01234567
                tx_data <= uart_data [cnt_bit-1]; //这里uart_data是不断随着cnt_bit变化的,只有在第九位的时候才有正确的最终值
                else if(cnt_bit == 0)
                tx_data <= 0 ;
                else if(cnt_bit == 9)
                tx_data <= (MODE_CHECK == 0)? ^uart_data: ~^uart_data;
              /*
              MODE_CHECK == 0是偶校验,假如uart_data是1110_0000,其异或的结果
              是1,将异或的结果作为校验位,让数据位和校验位异或的结果为0,满足偶校验。
              假如uart_data是1110_1000,其异或的结果是0,将异或的结果作为校验位,
              让数据位和校验位异或的结果为0,满足偶校验。奇校验则相反。
              */
                else if (cnt_bit == 10)///停止位
                tx_data <= 1 ;
                else
                tx_data <= tx_data ;
          end
          else
          tx_data <= 1 ;
          
          
       always@(posedge sys_clk )
          if(!rst_n)           
            tx_done <= 0 ;
          else if (tx_flag)begin
               if ( cnt_bit == 10 && cnt == COUNT -1)
//               if ( cnt_bit == 10 && cnt == MID/2 -1)
                   tx_done <= 1 ;
               else
                   tx_done <= 0 ;       
          end
          else
            tx_done <= 0 ;  
endmodule

四、仿真模块

(1)仿真true_ram模块

代码:

Matlab 复制代码
`timescale 1ns / 1ps
module test_the_true_ram( );

     reg                 sys_clk       ;
     reg                 rst_n         ;
     wire  [7:0]         ram_odd_data  ;
     wire  [7:0]         ram_even_data ;
     
     initial
            begin
                 sys_clk = 0 ;
                 rst_n   = 0 ;
                 #10  
                 rst_n = 1 ;
            end
           
     always #1 sys_clk = ~sys_clk ; 

    the_true_ram the_true_ram_1(
                                 .   sys_clk       (sys_clk      )    ,
                                 .   rst_n         (rst_n        )    ,
                                 .   ram_odd_data  (ram_odd_data )    ,
                                 .   ram_even_data (ram_even_data)
    );
    
    
    
    
endmodule

仿真结果:

(2)仿真TOP:

代码:

Matlab 复制代码
`timescale 1ns / 1ps
module test_TOP( );

  reg                sys_clk   ;
  reg                rst_n     ;
  reg                key_1     ;
  reg                key_2     ;
  wire               tx_data   ;
  
  initial
        begin
             sys_clk = 0 ;
             rst_n   = 0 ;
             key_1   = 1 ;
             key_2   = 1 ;
             #10
             rst_n   = 1 ;
             #10000
             key_1   = 0 ;

        end
  
  always #1 sys_clk = ~sys_clk ;
  
  
TOP TOP_1(
  .    sys_clk  (sys_clk)   ,
  .    rst_n    (rst_n  )   ,
  .    key_1    (key_1  )   ,
  .    key_2    (key_2  )   ,
  .    tx_data  (tx_data)  
    );



endmodule

仿真结果:

TOP:

single_ram_1 :

五、需要注意的一些问题

(1)

(2)

(3)控制模块最好这么写

Matlab 复制代码
`timescale 1ns / 1ps
module single_ram_2(
    input               sysclk          ,
    input               rst_n           ,
    input               key_flag1       ,
    input               key_flag2       ,
    input               tx_done         ,
    input       [7:0]   ram_odd_data    , //单数
    input       [7:0]   ram_even_data   , //双数
    output  reg         tx_start        ,
    output  reg [7:0]   uart_data            
    );
//存单数的RAM
reg          wea    ;
reg          ena    ;
reg   [6:0] addra  ;
reg   [7:0] dina   ;
wire  [7:0] douta  ;
///先写再读出
localparam      IDLE  = 3'd0;
localparam      WRITE = 3'd1; 地址加1
localparam      REG   = 3'd2;  ///缓冲状态   地址清零
localparam      READ  = 3'd3;
reg     [2:0]   cur_state,next_state;
reg             tx_start_a  ;
always@(posedge sysclk)
    if(!rst_n)
        cur_state <= IDLE;
    else
        cur_state <= next_state;
always@(*)
    case(cur_state)
        IDLE  : begin
            if(key_flag1)
                next_state = WRITE;
            else
                next_state = cur_state;
        end   
        WRITE :begin
            if(addra >= 49)
                next_state = REG;
            else
                next_state = cur_state; 
        end
        REG   :begin
            next_state = READ;
        end
        READ  :begin
            if(addra >= 49)
                next_state = IDLE;
            else
                next_state = cur_state;    
        end
        default:;
    endcase
always@(posedge sysclk)
    if(!rst_n)begin
        addra <= 0;
        wea <= 0;
        ena <= 0;
        dina <= 0;
        tx_start_a <= 0;
    end
    else
        case(cur_state)
            IDLE  :begin
                addra <= 0;
                wea <= 0;
                ena <= 0;
                dina <= ram_odd_data;  维持2个
            end
            WRITE :begin   ///99/48
                ena <= ~ena;     ///
                wea <= ~wea;     ///
                if(addra >= 49)
                    addra <= 49;
                else if(wea)
                    addra <= addra + 1; 
                dina <= ram_odd_data;
            end
            REG   :begin
                addra <= 0;
                ena <= 0;
                wea <= 0;
                dina <= 0;
                tx_start_a <= 1;   ///发送第一个数据
            end
            READ  :begin  
                ena <= 1;
                wea <= 0;
                dina <= 0;
                if(tx_done)begin
                    tx_start_a <= 1;
                    addra <= addra + 1;
                end
                else begin
                    tx_start_a <= 0;
                    addra <= addra;
                end     
            end
            default:; 
        endcase

blk_mem_gen_2 ram_a (
  .clka(sysclk),    // input wire clka
  .ena(ena),      // input wire ena
  .wea(wea),      // input wire [0 : 0] wea
  .addra(addra),  // input wire [6 : 0] addra
  .dina(dina),    // input wire [7 : 0] dina
  .douta(douta)  // output wire [7 : 0] douta
);
/b端口    存双数
reg             web   ;
reg             enb    ;
reg  [6:0]      addrb ;
reg  [7:0]      dinb  ;
wire [7:0]      doutb;
//状态机
///先写再读出
localparam      RD_IDLE  = 3'd4;
localparam      RD_WRITE = 3'd5;
localparam      RD_REG   = 3'd6;  ///缓冲状态
localparam      RD_READ  = 3'd7;
reg     [2:0]   rd_cur_state,rd_next_state;
reg             tx_start_b      ;
always@(posedge sysclk)
    if(!rst_n)
        rd_cur_state <= RD_IDLE;
    else
        rd_cur_state <= rd_next_state;
always@(*)
    case(rd_cur_state)
        RD_IDLE  : begin
            if(key_flag2)
                rd_next_state = RD_WRITE;
            else
                rd_next_state = rd_cur_state;
        end   
        RD_WRITE :begin
            if(addrb >= 49)
                rd_next_state = RD_REG;
            else
                rd_next_state = rd_cur_state; 
        end
        RD_REG   :begin
            rd_next_state = RD_READ;
        end
        RD_READ  :begin
            if(addrb >= 49)
                rd_next_state = RD_IDLE;
            else
                rd_next_state = rd_cur_state;    
        end
        default:;
    endcase
always@(posedge sysclk)
    if(!rst_n)begin
        addrb <= 0;
        web <= 0;
        enb <= 0;
        dinb <= 0;
        tx_start_b <= 0;
    end
    else
        case(rd_cur_state)
            RD_IDLE  :begin
                addrb <= 0;
                web <= 0;
                enb <= 0;
                dinb <= ram_even_data;  ///020406
            end
            RD_WRITE :begin
                enb <= ~enb;  
                web <= ~web;
                if(addrb >= 49)
                    addrb <= 49;
                else if(web)
                    addrb <= addrb + 1; 
                dinb <= ram_even_data;
            end
            RD_REG   :begin
                addrb <= 0;
                enb <= 0;
                web <= 0;
                dinb <= 0;
                tx_start_b <= 1;
            end
            RD_READ  :begin  
                enb <= 1;
                web <= 0;
                dinb <= 0;
                if(tx_done)begin
                    tx_start_b <= 1;
                    addrb <= addrb + 1;
                end
                else begin
                    tx_start_b <= 0;
                    addrb <= addrb;
                end     
            end
            default:; 
        endcase
blk_mem_gen_2 ram_b (
  .clka(sysclk),    // input wire clka
  .ena(enb),      // input wire ena
  .wea(web),      // input wire [0 : 0] wea
  .addra(addrb),  // input wire [6 : 0] addra
  .dina(dinb),    // input wire [7 : 0] dina
  .douta(doutb)  // output wire [7 : 0] douta
);
always@(posedge sysclk)
    if(!rst_n)
        uart_data <= 0;
    else if(cur_state == READ )
        uart_data <= douta  ;
    else if(rd_cur_state == RD_READ )
        uart_data <= doutb  ;
    else
        uart_data <= uart_data;
     
always@(posedge sysclk)
    if(!rst_n)
        tx_start <= 0;
    else if(cur_state == REG || cur_state == READ)
        tx_start <= tx_start_a;
    else if(rd_cur_state == RD_REG || rd_cur_state == RD_READ)
        tx_start <= tx_start_b;
    else
        tx_start <= tx_start;
           
endmodule
相关推荐
szxinmai主板定制专家1 小时前
【国产NI替代】基于FPGA的32通道(24bits)高精度终端采集核心板卡
大数据·人工智能·fpga开发
HIZYUAN7 小时前
AGM FPGA如何配置上拉或者下拉电阻
fpga开发
∑狸猫不是猫7 小时前
(13)CT137A- 简易音乐盒设计
fpga开发
ThreeYear_s13 小时前
基于FPGA 的4位密码锁 矩阵键盘 数码管显示 报警仿真
fpga开发·矩阵·计算机外设
Anin蓝天(北京太速科技-陈)19 小时前
252-8路SATAII 6U VPX高速存储模块
fpga开发
如何学会学习?21 小时前
2. FPGA基础了解--全局网络
fpga开发
Anin蓝天(北京太速科技-陈)1 天前
271-基于XC7V690T的12路光纤PCIe接口卡
嵌入式硬件·fpga开发
碎碎思1 天前
FPGA新闻速览-WiMi开发基于FPGA的数字量子计算机验证技术
fpga开发·量子计算
hi942 天前
Vivado - 远程调试 + 远程综合实现 + vmWare网络配置 + NFS 文件共享 + 使用 VIO 核
嵌入式硬件·fpga开发·vivado 远程开发·vmware网络配置
乘风~&2 天前
基于发FPGA 练手智能小车顶层文件
fpga开发