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不能使用同一个计数器,不然在同一个模块中也会判断出问题。

`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参数:

`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)

`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模块

配置和前面一样

`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模块:

`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模块

代码:

`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:

代码:

`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)控制模块最好这么写

`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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/780758.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

普通Java工程如何在代码中引用docker-compose.yml中的environment值

文章目录 一、概述二、常规做法1. 数据库配置分离2. 代码引用配置3. 编写启动类4. 支持打包成可执行包5. 支持可执行包打包成docker镜像6. docker运行 三、存在问题分析四、改进措施1. 包含environment 变量的编排文件2. 修改读取配置文件方式3. 为什么可以这样做 五、运行效果…

股票Level-2行情是什么,应该怎么使用,从哪里获取数据

行情接入方法 level2行情websocket接入方法-CSDN博客 相比传统的股票行情&#xff0c;Level-2行情为投资者打开了更广阔的视野&#xff0c;不仅限于买一卖一的表面数据&#xff0c;而是深入到市场的核心&#xff0c;提供了十档乃至千档的行情信息&#xff08;沪市十档&#…

JavaWeb-【1】HTML

笔记系列持续更新,真正做到详细!!本次系列重点讲解后端,那么第一阶段先讲解前端 目录 1、Javaweb技术体系 2、BS架构说明 3、官方文档 4、网页组成 5、HTML 6、HTML快速入门 7、HTML基本结构 8、HTML标签 ​9、HTML标签使用细节 ①、font标签 ②、字符实体 ③、标…

图神经网络dgl和torch-geometric安装

文章目录 搭建环境dgl的安装torch-geometric安装 在跑论文代码过程中&#xff0c;许多小伙伴们可能会遇到一些和我一样的问题&#xff0c;就是文章所需要的一些库的版本比较老&#xff0c;而新版的环境跑代码会报错&#xff0c;这就需要我们手动的下载whl格式的文件来安装相应的…

SSM中小学生信息管理系统 -计算机毕业设计源码02677

摘要 随着社会的发展和教育的进步&#xff0c;中小学生信息管理系统成为学校管理的重要工具。本论文旨在基于SSM框架&#xff0c;采用Java编程语言和MySQL数据库&#xff0c;设计和开发一套高效、可靠的中小学生信息管理系统。中小学生信息管理系统以学生为中心&#xff0c;通过…

机器学习筑基篇,​Ubuntu 24.04 编译安装 Python 及多版本切换

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] Ubuntu 24.04 编译安装最新Python及多版本切换 描述&#xff1a;说到机器学习&#xff0c;人工智能&#xff0c;深度学习不免会提到Python这一门编程语言&#xff08;人生苦短&#xff0c;及时Pyt…

【MySQL】逻辑架构与存储引擎

一、逻辑架构 1、MySQL逻辑架构 我们可以根据上图来对sql的执行过程进行分析 第一步&#xff1a;客户端与服务器建立一个连接&#xff0c;从连接池中分配一个线程处理SQL语句第二步&#xff1a;SQL接口接受SQL指令第三步&#xff1a;如果是5.7版本&#xff0c;就会先去缓存中…

Facebook数据仓库的变迁与启示

❃博主首页 &#xff1a; <码到三十五> ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a; <搬的每块砖&#xff0c;皆为峰峦之基&#xff1b;公众号搜索(码到…

史上最全的自抗扰控制(ADRC)学习资料

史上最全的自抗扰控制&#xff08;ADRC&#xff09;学习资料 需要的私信我~ 需要的私信我~ 需要的私信我~ ​ 本文将作者近些年来学习ADRC算法的学习资料进行汇总&#xff0c;整理了这一版相对较全的学习资料&#xff0c;包含参考文献以及仿真案例&#xff0c;适合初学者入门&…

STM32实现看门狗(HAL库)

文章目录 一. 看门狗1. 独立看门狗&#xff08;IWDG&#xff09;1.1 原理1.2 相关配置1.3 相关函数 2. 窗口看门狗&#xff08;WWDG&#xff09;2.1 原理2.2 相关配置2.3 相关函数 一. 看门狗 单片机在日常工作中常常会因为用户配置代码出现BUG&#xff0c;而导致芯片无法正常工…

21天学通C++:第九、十章节

第九章&#xff1a;类和对象 带默认值的构造函数参数 注意&#xff1a;默认构造函数是调用时可不提供参数的构造函数&#xff0c;而并不一定是不接受任何参数的构造函数。 因此&#xff0c;下面的构造函数虽然有两个参数&#xff0c;但它们都有默认值&#xff0c;因此也是默认…

CurrentHashMap巧妙利用位运算获取数组指定下标元素

先来了解一下数组对象在堆中的存储形式【数组长度&#xff0c;数组元素类型信息等】 【存放元素对象的空间】 Ma 基础信息实例数据内存填充Mark Word,ClassPointer,数组长度第一个元素第二个元素固定的填充内容 所以我们想要获取某个下标的元素首先要获取这个元素的起始位置…

Java 有什么必看的书?

Java必看经典书有这两本&#xff1a; 1、Java核心技术速学版&#xff08;第3版&#xff09; 经典Java开发基础书CoreJava速学版本&#xff01;Java入门优选书籍&#xff0c;更新至Java17&#xff0c;内容皆是精华&#xff0c;让Java学习更简单&#xff0c;让Java知识应用更快速…

fasttext工具介绍

fastText是由Facebook Research团队于2016年开源的一个词向量计算和文本分类工具。尽管在学术上并未带来巨大创新&#xff0c;但其在实际应用中的表现却非常出色&#xff0c;特别是在文本分类任务中&#xff0c;fastText往往能以浅层网络结构取得与深度网络相媲美的精度&#x…

STM32CubeMX实现4X5矩阵按键(HAL库实现)

为了实现计算器键盘&#xff0c;需要使用4X5矩阵按键&#xff0c;因此&#xff0c;我在4X4矩阵键盘上重新设计了一个4X5矩阵按键。原理图如下&#xff1a; 原理描述&#xff1a; 4X5矩阵按键&#xff0c;可以设置4个引脚为输出&#xff0c;5个引脚为输入模式&#xff0c;4个引…

MPS---MPQ86960芯片layout设计总结

MPQ86960 是一款内置功率 MOSFET 和栅极驱动的单片半桥。它可以在宽输入电压 (VIN) 范围内实现高达 50A 的连续输出电流 (IOUT)&#xff0c;通过集成MOSFET 和驱动可优化死区时间 (DT) 并降低寄生电感&#xff0c;从而实现高效率。 MPQ86960 兼容三态输出控制器&#xff0c;另…

Ubantu22.04 通过FlatPak安装微信

Ubuntu22.04 下使用Flatpak稳定安装微信&#xff01; 国际惯例&#xff0c;废话不多说&#xff0c;先上效果图。为啥使用Flatpak,因为Wechat官方只在FlatPak发布了最新的版本。之前使用了Wine以及Dock安装Wechat,效果都不是很理想&#xff0c;bug很多。所以使用了FlatPak。 Fl…

GRPC使用之ProtoBuf

1. 入门指导 1. 基本定义 Protocol Buffers提供一种跨语言的结构化数据的序列化能力&#xff0c;类似于JSON&#xff0c;不过更小、更快&#xff0c;除此以外它还能用用接口定义(IDL interface define language)&#xff0c;通protoc编译Protocol Buffer定义文件&#xff0c;…

【Spring Cloud】微服务的简单搭建

文章目录 &#x1f343;前言&#x1f384;开发环境安装&#x1f333;服务拆分的原则&#x1f6a9;单一职责原则&#x1f6a9;服务自治&#x1f6a9;单向依赖 &#x1f340;搭建案例介绍&#x1f334;数据准备&#x1f38b;工程搭建&#x1f6a9;构建父子工程&#x1f388;创建父…