0

USB3.0通信用にFT600 16ビットチップとインターフェースしています。コンピュータは FT600 を介して FPGA と通信し、その逆も同様です。適切な信号をアサートし、データをメモリに書き込む FSM を作成しました。

問題: ハードウェアではなく FPGA コードに問題があると思いますが、1 バイトおきにメモリに正しく記録されているように見えます。

参照しているタイミング図は 16 ページにあります: http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT600Q-FT601Q%20IC%20Datasheet.pdf

これは私のFSMコードです:

parameter [4:0] S1 =    5'd0, //Neutral state
                        S2 =    5'd1, //Data transfer from FPGA to Computer
                        SA_1 = 5'd8,
                        SA_2 = 5'd9,
                        S3 =    5'd2, //Data transfer from Computer to FPGA
                        S4 =    5'd3,
                        S5 =    5'd4,
                        S6 =    5'd5,
                        S7 =    5'd6,
                        S8 =    5'd7;
reg [4:0] state=0;
reg [4:0] nstate=0;

//wire [15:0] wdata;
wire [15:0] rdata;
//Counter c1 (wdata, Cclock);

assign rdata = (state == S5) ? DATA_I :  rdata; //Holds the recieved data on DATA
assign DATA_O = (state == S7) ? rdata :  16'bz; //rdata : 16'bz;    //{8'h41,8'h41} :  16'bz; //Sends the transmitted data on DATA
reg OE_N_reg = 1;//Confirmation signal when Computer writes data to FPGA
reg RD_N_reg = 1;//Confirmation signal when Computer writes data to FPGA
reg WR_N_reg = 1;//Confirmation signal when FPGA writes data to Computer

assign OE_N = OE_N_reg;
assign RD_N = RD_N_reg;
assign WR_N = WR_N_reg;

//ByteEnable configuration based on state
assign BE[0] = (state == S3) ? 1'bz :  1; 
assign BE[1] = (state == S3) ? 1'bz :  1;

//Debugging outputs
//assign GPIO_O[7:3] = 0;
//assign GPIO_O[2] = OE_N;
//assign GPIO_O[3] = RD_N;
//assign GPIO_O[4] = WR_N;
//assign GPIO_O[7:5] = DATA[2:0];

//State Logic
always@(*) 
begin
    case(state)
        S1:if(TXE_N == 0)
            begin
                    nstate <= S2;
            end

            else
            begin
                if(RXF_N == 0)
                begin
                    nstate <= SA_1;
                end

                else
                begin
                    nstate <= S1;
                end
            end

        S2:if(TXE_N == 0)
            begin
                nstate <= SA_2;
            end

            else
            begin
                nstate <= S1;       
            end
        SA_1: if(RXF_N == 0)
            begin
                nstate <= S3;
            end

            else
            begin
                nstate <= S1;   
            end 
        S3:if(RXF_N == 0)
            begin
                nstate <= S4;
            end

            else
            begin
                nstate <= S1;   
            end
        S4:if(RXF_N == 0)
            begin
                nstate <= S5;
            end

            else
            begin
                nstate <= S1;   
            end
        S5:if(RXF_N == 0)
            begin
                nstate <= S5;
            end

            else
            begin
                nstate <= S6;   
            end
        S6: nstate <= S1;
        SA_2: if(TXE_N == 0)
            begin
                nstate <= S7;
            end

            else
            begin
                nstate <= S1;
            end
        S7: if(TXE_N == 0)
            begin
                nstate <= S7;
            end

            else
            begin
                nstate <= S8;       
            end
        S8: nstate <= S1;


        default:    nstate <= S1;

    endcase
end

//Output Assignment
always@(negedge S_AXI_ACLK) 
begin
    case(state)
        S1: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end

        S2: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end
        SA_1: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end

        S3: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end
        S4: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 0;
            DATA_T   <= 1;
            end
        S5: begin

            RD_N_reg <= 0;
            WR_N_reg <= 1;
            OE_N_reg <= 0;
            DATA_T   <= 1;
            end
        S6: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end
        SA_2: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end
        S7: begin

            RD_N_reg <= 1;
            WR_N_reg <= 0;
            OE_N_reg <= 1;
            DATA_T   <= 0;
            end
        S8: begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
            end


        default:    begin

            RD_N_reg <= 1;
            WR_N_reg <= 1;
            OE_N_reg <= 1;
            DATA_T   <= 1;
                    end
    endcase
end


//Update states
always@(negedge S_AXI_ACLK) 
begin
    state <= nstate;
end

//RECORD rdata INTO MEM:
always @(negedge Bus2IP_Clk) 
begin
    if((RD_N == 0)) begin
        s <= s+(11'd15);
        ram[0][0][s] <= rdata[15:0];
    end
    read_address <= mem_address; //AXI4 stuff
end

アイデア/提案はありますか?例として FT600 の簡単なコードが既に存在する場合は、リンクをいただければ幸いです。

4

1 に答える 1

0

ここにヒントがあります: 巨大な case ステートメントをこれに置き換えてください。まったく同じことを行いますが、使用するスペースがはるかに少なく、理解しやすいです。

always@(negedge S_AXI_ACLK) 
begin
    RD_N_reg <= 1;
    WR_N_reg <= 1;
    OE_N_reg <= 1;
    DATA_T   <= 1;
    case(state)
        S4: OE_N_reg <= 0;
        S5: begin
            RD_N_reg <= 0;
            OE_N_reg <= 0;
            end
        S7: begin
            WR_N_reg <= 0;
            DATA_T   <= 0;
            end
    endcase
end

ブロックの上部にある 4 つの割り当ては、デフォルトの割り当てと呼ばれ、コードをよりコンパクトにして理解しやすくするのに役立ちます。

于 2016-06-30T15:08:34.833 に答える