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裡面的wrfull和rdempty訊號,並不是延遲一個時鐘出來的,而是延遲兩個;
(2)fifo裡面的wrusedw或者rdusedw,要等它反映過來,貌似是延遲4個時鐘。而且這兩個訊號是可以用最高位來看fifo是否滿半來做一些其它的操作的。
(3)Fifo的aclr是高有效而產生復位
暫時就想到這麼多,先寫這麼多,其實實現起來也很簡單,主要寫這個主要是為了以後多閱讀英文文獻,先從fifo user guide來入手研究一下容易點。