1. 程式人生 > >verilog實現串列埠

verilog實現串列埠

主要記錄自己在利用verilog實現串列埠的時候一些簡單的介紹和遇到問題和思考。備忘

1、串列埠傳輸格式,可以百度,有很多也很簡單。串列埠分為兩部分,一個收,一個發。所以在verilog實現時可以把這兩部分分開。也就是兩個fifo配套收和發的.v檔案,可以實現一個串列埠。一般人實現串列埠的都是這麼想的吧。下面是檔案的層級結構:


2、當然是coding了。寫串列埠的程式碼。主要貼一下收和發的狀態機(用一段來實現的):

(1)這是收的部分:

case(state_rxd)

state_rxd_idle :  //0

begin

finished_rxd <= 1'b0;

rxd_error <= 1'b0;

if((!rxd_write_full) && ({port_rxd_d3,port_rxd_d2,port_rxd_d1}==3'b100))

begin

state_rxd <= state_rxd_head;

time_rxd <= 1'd0;

end

else

state_rxd <= state_rxd_idle;

end

state_rxd_head : //1

begin

if((time_rxd == rxd_half_band_rate) && ({port_rxd_d3,port_rxd_d2,port_rxd_d1}==3'b000))

begin

time_rxd <= 15'd0;

state_rxd <= state_rxd_rxd;

data_rxd_d1 <= 8'd0;

end

else if((time_rxd == rxd_half_band_rate) && ({port_rxd_d3,port_rxd_d2,port_rxd_d1}!=3'b000))

begin

time_rxd <= 15'd0;

state_rxd <= state_rxd_idle;

end

else

time_rxd <= time_rxd + 1;

end

state_rxd_rxd : //2

begin

if((time_rxd == rxd_band_rate))

begin

time_rxd <= 15'd0;

if(count_rxd_bit == 3'd7)

begin

count_rxd_bit <= 3'd0;

state_rxd <= state_rxd_tail;

data_rxd_d1 <= {port_rxd_d1,data_rxd_d1[7:1]};

end

else

begin

count_rxd_bit <= count_rxd_bit + 1;

data_rxd_d1 <= {port_rxd_d1,data_rxd_d1[7:1]};

end

end

else

begin

time_rxd <= time_rxd + 1;

end

end

state_rxd_tail : //3

begin

if((time_rxd == rxd_band_rate) && ({port_rxd_d3,port_rxd_d2,port_rxd_d1}==3'b111))

begin

rxd_error <= 1'd0;

finished_rxd <= 1'b1;

state_rxd <= state_rxd_idle;

end

else if((time_rxd == rxd_band_rate) && ({port_rxd_d3,port_rxd_d2,port_rxd_d1}!=3'b111))

begin

rxd_error <= 1'd1;

finished_rxd <= 1'b0;

state_rxd <= state_rxd_idle;

end

else

begin

finished_rxd <= 1'b0;

rxd_error <= 1'b0;

time_rxd <= time_rxd + 1;

end

end

default : state_rxd <= state_rxd_idle;

Endcase

(2)這是發的部分:

case(state_txd)

state_txd_idle :  //0

begin

time_txd <= 15'd0;

finished_send <= 1'b0;

if(load_data_tag_d1 == 1'b1)

begin

state_txd <= state_txd_head;

data_txd_reg1 <= data_txd_reg;

end

else

state_txd <= state_txd;

end

state_txd_head : //1

begin

port_txd_reg <= 1'b0;

if(time_txd == txd_band_rate)

begin

time_txd <= 15'd0;

state_txd <= state_txd_txd;

end

else

time_txd <= time_txd + 1;

end

state_txd_txd : //2

begin

port_txd_reg <= data_txd_reg1[0];

if(time_txd == txd_band_rate)

begin

time_txd <= 15'd0;

if(count_bit_send == 3'd7)

begin

count_bit_send <= 3'd0;

state_txd <= state_txd_tail;

end

else

begin

count_bit_send <= count_bit_send + 1;

data_txd_reg1 <= {1'b0,data_txd_reg1[7:1]};

end

end

else

time_txd <= time_txd + 1;

end

state_txd_tail : //3

begin

port_txd_reg <= 1'b1;

if(time_txd == txd_band_rate)

begin

state_txd <= state_txd_idle;

finished_send <= 1'b1;

end

else

begin

finished_send <= 1'b0;

time_txd <= time_txd + 1;

end

end

default:

begin

port_txd_reg <= 1'b1;

finished_send <= 1'b0;

time_txd <= 15'd0;

data_txd_reg1 <= 8'd0;

end

Endcase

3、測試串列埠:

測試方法主要是通過自己把fifo寫成迴路來測試,相當於上位機發資料給fpga,然後fpga自己把資料通過串列埠傳給上位機,對比傳入和傳出的資料是否一樣來驗證。這樣測試對於一般串列埠的應用是應該夠了。


4,除錯過程中遇到問題:

(1)fifo裡面的wrfullrdempty訊號,並不是延遲一個時鐘出來的,而是延遲兩個;

(2)fifo裡面的wrusedw或者rdusedw,要等它反映過來,貌似是延遲4個時鐘。而且這兩個訊號是可以用最高位來看fifo是否滿半來做一些其它的操作的。

(3)Fifoaclr是高有效而產生復位

暫時就想到這麼多,先寫這麼多,其實實現起來也很簡單,主要寫這個主要是為了以後多閱讀英文文獻,先從fifo user guide來入手研究一下容易點。