#问题描述:写一个状态机,想用计数器计数到特定数值时,跳转到下一个状态,比如计数器计到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
行为仿真时波形
综合后仿真