sinat_42741346 2023-07-19 15:27 采纳率: 50%
浏览 56
已结题

vivado 计数器数拍儿但数值高阻

#问题描述:写一个状态机,想用计数器计数到特定数值时,跳转到下一个状态,比如计数器计到15到下一个状态,行为仿真时没有问题,综合后仿真计数器数拍儿了,但是计的数值都是高阻
,代码和波形现象如下。

#问题背景:初学fpga开发,想实现功能:有个usb转fifo接口芯片,在fpga例化2个fifo,一个收一个发,收fifo将接口芯片数据收进来,然后在FPGA内部处理,处理完之后通过发fifo送回接口芯片。

(1)顶层,例化了两个fifo


module des_usb(
    input           clk            , 
    input           rst_n          ,
    input           usb_rxf_n      ,
    input           usb_txe_n      ,
    output          usb_oe_n       ,
    output          usb_wr_n       ,
    output          usb_rd_n       ,
    output          usb_siwu_n     ,
    inout  [7:0]    usb_data
 );

 wire      [7:0]    usb_bus_2_fifo;
 wire      [7:0]    fifo_2_usb_bus;
 wire      [7:0]    recv_fifo_out ;
 wire               recv_empty    ;
 wire               recv_full     ;
 wire               send_empty    ;
 wire               send_full     ;
 wire               usb_bus_ctl   ;
 wire      [7:0]    send_data     ;
 wire               recv_wr       ;
 wire               recv_rd       ;
 wire               send_wr       ;
 wire               send_rd       ;
 
 assign  usb_siwu_n = 1'b1;          //立即发送,唤醒
 
 usb_ctl  u_usb_ctl(
    .clk            (clk                  ),
    .rst_n          (rst_n                ),
    .usb_rxf_n      (usb_rxf_n            ),
    .usb_txe_n      (usb_txe_n            ),
    .recv_full      (recv_full            ),
    .recv_empty     (recv_empty           ),
    .send_full      (send_full            ),
    .send_empty     (send_empty           ),
    .din            (recv_fifo_out        ),
    .recv_wr        (recv_wr              ),
    .recv_rd        (recv_rd              ),
    .send_wr        (send_wr              ),
    .send_rd        (send_rd              ),
    .usb_oe_n       (usb_oe_n             ),
    .usb_wr_n       (usb_wr_n             ),
    .usb_rd_n       (usb_rd_n             ),
    .usb_ctl        (usb_bus_ctl          ),
    .dout           (send_data            )
 );
 
 assign  usb_data = (usb_bus_ctl)? fifo_2_usb_bus : 8'bz;
 assign  usb_bus_2_fifo = usb_data;
 
 fifo_generator_0 u_fifo_recv (
  .clk              (clk                  ), // input wire clk
  .srst             (!rst_n               ),
  .din              (usb_bus_2_fifo       ), // input wire [7 : 0] din
  .wr_en            (recv_wr              ), // input wire wr_en
  .rd_en            (recv_rd              ), // input wire rd_en
  .dout             (recv_fifo_out        ), // output wire [7 : 0] dout
  .full             (recv_full            ), // output wire full
  .empty            (recv_empty           )  // output wire empty
);

 fifo_generator_0 u_fifo_send (
  .clk              (clk                  ),  // input wire clk
  .srst             (!rst_n               ),
  .din              (send_data            ),  // input wire [7 : 0] din
  .wr_en            (send_wr              ),  // input wire wr_en
  .rd_en            (send_rd              ),  // input wire rd_en
  .dout             (fifo_2_usb_bus       ),  // output wire [7 : 0] dout
  .full             (send_full            ),  // output wire full
  .empty            (send_empty           )   // output wire empty
);

endmodule

(2)usb_ctl模块

module usb_ctl(
    input                              clk            , 
    input                              rst_n          ,
    input                              usb_rxf_n      ,
    input                              usb_txe_n      ,
    input                              recv_full      ,
    input                              recv_empty     ,
    input                              send_full      ,
    input                              send_empty     ,
    input           [7:0]              din            ,
    output     reg                     recv_wr        ,
    output     reg                     recv_rd        ,
    output     reg                     send_wr        ,
    output     reg                     send_rd        ,
    output     reg                     usb_oe_n       ,
    output     reg                     usb_wr_n       ,
    output     reg                     usb_rd_n       ,
    output     reg                     usb_ctl        ,
    output     reg  [7:0]              dout           
);
    
localparam    IDLE = 3'd1;
localparam    R_WR = 3'd2;
localparam    R_RD = 3'd3;
localparam    PROC = 3'd4;
localparam    S_WR = 3'd5;
localparam    S_RD = 3'd6;

reg        [2:0]   curr_state          ;
reg        [2:0]   next_state          ;
reg                usb_oe_n_d0         ; 
reg        [4:0]   recv_wr_cnt         ;
reg        [4:0]   recv_rd_cnt         ;
reg        [4:0]   send_wr_cnt         ;
reg        [4:0]   send_rd_cnt         ;
reg        [4:0]   wait_cnt            ;
reg      [127:0]   recv_data           ;
reg                proc_done           ;
reg                proc_done_d0        ;
reg                proc_done_d1        ;
wire      [63:0]   plain               ;
wire      [63:0]   key                 ;
wire      [63:0]   cipher              ;

//usb_oe_n
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        usb_oe_n_d0 <= 1'b1;
    else if(usb_rxf_n == 1'b0)
        usb_oe_n_d0 <= 1'b0;
    else
        usb_oe_n_d0 <= 1'b1;
end

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        usb_oe_n <= 1'b1;
    else
        usb_oe_n <= usb_oe_n_d0;
end

//״̬»ú
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        curr_state <= IDLE;   
    else 
        curr_state <= next_state; 
end

always@(*)begin
    case(curr_state)
        IDLE : begin
            if(usb_oe_n_d0 == 0 && usb_oe_n == 0 && proc_done == 1'b0) begin
                usb_rd_n = 1'b0;
                usb_wr_n = 1'b1;
                recv_wr = 1'b1;
                recv_rd = 1'b0;
                send_wr = 1'b0;
                send_rd = 1'b0;
                usb_ctl = 1'b0;
                next_state = R_WR;
        end
        else
            next_state = IDLE;    
        end
        R_WR : begin
            if(recv_wr_cnt == 5'd15 ) begin
                usb_rd_n = 1'b1;
                usb_wr_n = 1'b1;            
                recv_wr = 1'b0;
                recv_rd = 1'b1;
                send_wr = 1'b0;
                send_rd = 1'b0;
                usb_ctl = 1'b0;            
                next_state = R_RD;
            end
            else
                next_state = R_WR;
        end
        R_RD : begin
            if(recv_rd_cnt == 5'd15 ) begin
                usb_rd_n = 1'b1;
                usb_wr_n = 1'b1;
                recv_wr = 1'b0;
                recv_rd = 1'b0;
                send_wr = 1'b0;
                send_rd = 1'b0;
                usb_ctl = 1'b0;            
                next_state = PROC;
            end
            else
                next_state = R_RD;
        end
        PROC : begin
            if(proc_done)begin
                usb_rd_n = 1'b1;
                usb_wr_n = 1'b1;
                recv_wr = 1'b0;
                recv_rd = 1'b0;
                send_wr = 1'b0;
                send_rd = 1'b0;
                usb_ctl = 1'b0;
                next_state = S_WR;    
            end
            else        
                next_state = PROC;
        end
        S_WR : begin
            if(send_wr_cnt == 5'd7 ) begin
                usb_rd_n = 1'b1;
                usb_wr_n = 1'b0;
                recv_wr = 1'b0;
                recv_rd = 1'b0;
                send_rd = 1'b1;
                usb_ctl = 1'b1;            
                next_state = S_RD;
            end
            else begin
                next_state = S_WR;
                send_wr = 1'b1;
            end
        end    
        S_RD : begin
            if(send_rd_cnt == 5'd8 ) begin
                usb_rd_n = 1'b1;
                usb_wr_n = 1'b1;
                recv_wr = 1'b0;
                recv_rd = 1'b0;
                send_wr = 1'b0;
                send_rd = 1'b0;
                usb_ctl = 1'b0;            
                next_state = IDLE;
            end
            else    
                next_state = S_RD;
        end    
        default: next_state = IDLE;
        endcase
end

//recv_wr_cnt
always @ (posedge clk or negedge rst_n) begin
    if(!rst_n)
        recv_wr_cnt <= 5'd0;
    else if(curr_state == R_WR)
        recv_wr_cnt <= recv_wr_cnt + 5'b1;
    else
        recv_wr_cnt <= 5'd0;
end

//recv_rd_cnt
always @ (posedge clk or negedge rst_n) begin
    if(!rst_n)
        recv_rd_cnt <= 5'd0;
    else if(curr_state == R_RD)
        recv_rd_cnt <= recv_rd_cnt + 5'b1;
    else
        recv_rd_cnt <= 5'd0;
end

always @ (recv_rd_cnt) begin
    case(recv_rd_cnt)
        5'd1 :  recv_data[127:120] = din;
        5'd2 :  recv_data[119:112] = din;
        5'd3 :  recv_data[111:104] = din;
        5'd4 :  recv_data[103: 96] = din;
        5'd5 :  recv_data[ 95: 88] = din;
        5'd6 :  recv_data[ 87: 80] = din;
        5'd7 :  recv_data[ 79: 72] = din;
        5'd8 :  recv_data[ 71: 64] = din;
        5'd9 :  recv_data[ 63: 56] = din;
        5'd10:  recv_data[ 55: 48] = din;
        5'd11:  recv_data[ 47: 40] = din;
        5'd12:  recv_data[ 39: 32] = din;
        5'd13:  recv_data[ 31: 24] = din;
        5'd14:  recv_data[ 23: 16] = din;
        5'd15:  recv_data[ 15:  8] = din;
        5'd16:  recv_data[  7:  0] = din;
    default   : ;                       
    endcase
end

 assign  key =  recv_data[127:64];
 assign  plain =  recv_data[63:0];
 assign  cipher = key^plain; 
 
 always @ (posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        proc_done <= 1'b0;
        proc_done_d0 <= 1'b0;
        proc_done_d1 <= 1'b0;
    end
    else if(curr_state == PROC) begin
        proc_done_d0 <= 1'b1;
        proc_done_d1 <= proc_done_d0;
        proc_done <= proc_done_d0;
    end    
 end

//send_wr_cnt
always @ (posedge clk or negedge rst_n) begin
    if(!rst_n)
        send_wr_cnt <= 5'd0;
    else if(next_state == S_WR)
        send_wr_cnt <= send_wr_cnt + 5'b1;
    else
        send_wr_cnt <= 5'd0;
end
      
always @ (posedge clk) begin
    case(send_wr_cnt)
        5'd0 :  dout <= cipher[ 63: 56];
        5'd1 :  dout <= cipher[ 55: 48];
        5'd2 :  dout <= cipher[ 47: 40];
        5'd3 :  dout <= cipher[ 39: 32];
        5'd4 :  dout <= cipher[ 31: 24];
        5'd5 :  dout <= cipher[ 23: 16];
        5'd6 :  dout <= cipher[ 15:  8];
        5'd7  : dout <= cipher[  7:  0];
    default   : ;                       
    endcase
end

//send_rd_cnt
always @ (posedge clk or negedge rst_n) begin
    if(!rst_n)
        send_rd_cnt <= 5'd0;
    else if(curr_state == S_RD)
        send_rd_cnt <= send_rd_cnt + 5'b1;
    else
        send_rd_cnt <= 5'd0;
end

endmodule

tb


`timescale 1ns / 1ps

module tb_des_usb();
reg                 clk               ;
reg                 rst_n             ;
reg                 usb_rxf_n         ;
reg                 usb_txe_n         ;
wire                usb_oe_n          ;
wire                usb_wr_n          ;
wire                usb_rd_n          ;
wire        [7:0]   usb_data          ;

reg                 tb_ctl            ;
reg         [7:0]   usb_data_reg      ;
reg         [3:0]   tb_cnt            ;
reg                 usb_rd_n_d0       ;
reg                 usb_rd_n_d1       ;
wire                tb_flag           ;

initial begin
    clk = 1'b0;
    rst_n = 1'b1;
    tb_ctl = 1'b1; 
    usb_rxf_n = 1'b0;
    usb_txe_n = 1'b0;
    #10 rst_n = 1'b0;
    #10 rst_n = 1'b1;
    #15 tb_ctl = 1'b0; //行为仿真时,用这个
//    #105 tb_ctl = 1'b0; //综合后仿真时,用这个
    usb_data_reg = 8'hbb;
    #10 usb_data_reg = 8'h34;
    #10 usb_data_reg = 8'h56;
    #10 usb_data_reg = 8'h78;
    #10 usb_data_reg = 8'h9a;
    #10 usb_data_reg = 8'hbc;
    #10 usb_data_reg = 8'hde;
    #10 usb_data_reg = 8'hf0;
    #10 usb_data_reg = 8'h0f;
    #10 usb_data_reg = 8'h1e;
    #10 usb_data_reg = 8'h56;
    #10 usb_data_reg = 8'h64;
    #10 usb_data_reg = 8'h32;
    #10 usb_data_reg = 8'h23;
    #10 usb_data_reg = 8'h34;
    #10 usb_data_reg = 8'hee;
    #10 tb_ctl = 1'b1; 
end
assign  usb_data = (tb_ctl == 0) ? usb_data_reg : 8'hz;  
always  #5  clk = ~clk;

des_usb  u_des_usb(
    .clk          (clk                   ),
    .rst_n        (rst_n                 ),
    .usb_rxf_n    (usb_rxf_n             ),
    .usb_txe_n    (usb_txe_n             ),
    .usb_oe_n     (usb_oe_n              ), 
    .usb_wr_n     (usb_wr_n              ),
    .usb_rd_n     (usb_rd_n              ),
    .usb_data     (usb_data              )  
);
    
endmodule

行为仿真时波形

img

综合后仿真

img

  • 写回答

3条回答 默认 最新

  • 藏柏 2023-07-19 15:42
    关注

    从代码中看,状态机似乎是在正常工作的,但是你提到计数器数值都是高阻的,这可能是因为计数器的输出没有被连接到任何输出端口,导致无法观察到计数器的值。

    在你的代码中,recv_wr_cntrecv_rd_cntsend_wr_cntsend_rd_cnt这些计数器变量被使用来控制状态转移和一些输出信号的操作。如果你想观察这些计数器的值,你可以将它们连接到相应的输出端口,并通过外部监视器或测试台来观察计数器的值。

    例如,你可以将以下代码添加到你的模块中,将计数器的值作为输出端口,并在测试台上显示:

    module usb_ctl(
        // 其他端口声明
        output reg [4:0] recv_wr_cnt_out,
        output reg [4:0] recv_rd_cnt_out,
        output reg [4:0] send_wr_cnt_out,
        output reg [4:0] send_rd_cnt_out
        // 其他端口声明
    );
        // 其他逻辑
        
        always @(posedge clk) begin
            recv_wr_cnt_out <= recv_wr_cnt;
            recv_rd_cnt_out <= recv_rd_cnt;
            send_wr_cnt_out <= send_wr_cnt;
            send_rd_cnt_out <= send_rd_cnt;
        end
    endmodule
    

    然后,在测试台上检查输出信号 recv_wr_cnt_outrecv_rd_cnt_outsend_wr_cnt_outsend_rd_cnt_out的值,以验证计数器的正确性。

    请注意,以上仅是一种示例方式,你可以根据需要将计数器的值连接到其他输出端口或使用其他方法来观察计数器的值。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 7月29日
  • 已采纳回答 7月21日
  • 修改了问题 7月19日
  • 创建了问题 7月19日

悬赏问题

  • ¥15 请问GPT语言模型怎么训练?
  • ¥15 已知平面坐标系(非直角坐标系)内三个点的坐标,反求两坐标轴的夹角
  • ¥15 webots有问题,无响应
  • ¥15 数据量少可以用MK趋势分析吗
  • ¥15 使用VH6501干扰RTR位,CANoe上显示的错误帧不足32个就进入bus off快慢恢复,为什么?
  • ¥15 大智慧怎么编写一个选股程序
  • ¥100 python 调用 cgps 命令获取 实时位置信息
  • ¥15 两台交换机分别是trunk接口和access接口为何无法通信,通信过程是如何?
  • ¥15 C语言使用vscode编码错误
  • ¥15 用KSV5转成本时,如何不生成那笔中间凭证