verilogシリアルポートが複数のデータを受信して処理する実現方法
18365 ワード
シリアルポートを用いて複数のデータを受信して処理する問題について、現在ネット上に存在するverilogシリアルポート通信に関する資料は、シリアルポートを用いて単一文字の受信と送信を実現することを説明するものである.一方、シリアルポートを使用して通信する場合、データ端子はシリアルポートを通じて多くのデータを受信し、すべてのデータが受信されたり、何らかの条件に達したりした後、自分の後続の仕事を開始する必要があります.だからここで私は自分のいくつかの具体的な実現過程とverilogソースコードを分かち合って、みんなに役に立つことを望んでいます.(ここではシリアルポートを利用してデータを受信して処理する部分だけを話して、その部分を送信してから共有します)まずインターネット上の多くのシリアルポートで受信したコードを貼って、以下のようにします.
ここでは概ねシリアルポートが1回のデータを受信する処理過程であり、データを受信した後に送信フラグビットを生成し、データの送信を開始するが、ここでいうデータキャッシュ処理には2つの解決方法があり、1つ目は16進数転送であるため、転送ごとに有効なデータは8ビットであるため、1つのレジスタreg[23:0]rx_を定義するcnt;長さ8の整数倍、シフト方式でデータを格納し、上記コードではNUMカウントが11になると1回データ転送が完了するのでnum=11のところに
そして元の出力ポートassign rx_data = rx_data_r;削除して、新しい出力受信の完全なコードを書きます.
ボーレートプロファイルはネット上のコードが多いので、ここでは貼らない.
module my_uart_rx(
clk,rst_n,
rs232_rx,rx_data,rx_int,
clk_bps,bps_start
);
input clk; // 50MHz
input rst_n; //
input rs232_rx; // RS232
input clk_bps; // clk_bps
output bps_start; // ,
output[7:0] rx_data; // ,
output rx_int; // ,
//----------------------------------------------------------------
reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3; // ,
wire neg_rs232_rx; //
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
rs232_rx0 <= 1'b0;
rs232_rx1 <= 1'b0;
rs232_rx2 <= 1'b0;
rs232_rx3 <= 1'b0;
end
else begin
rs232_rx0 <= rs232_rx;
rs232_rx1 <= rs232_rx0;
rs232_rx2 <= rs232_rx1;
rs232_rx3 <= rs232_rx2;
end
end
// <20ns-40ns ( ),
// ( , )
//( 40ns )
assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0; // neg_rs232_rx
//----------------------------------------------------------------
reg bps_start_r;
reg[3:0] num; //
reg rx_int; // ,
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
bps_start_r <= 1'bz;
rx_int <= 1'b0;
end
else if(neg_rs232_rx) begin // rs232_rx
bps_start_r <= 1'b1; //
rx_int <= 1'b1; //
end
else if(num==4'd11) begin // /// num 11. 12!!
bps_start_r <= 1'b0; // ,
rx_int <= 1'b0; //
end
assign bps_start = bps_start_r;
//----------------------------------------------------------------
reg[7:0] rx_data_r; // ,
//----------------------------------------------------------------
reg[7:0] rx_temp_data; //
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
rx_temp_data <= 8'd0;
num <= 4'd0;
rx_data_r <= 8'd0;
end
else if(rx_int) begin //
if(clk_bps) begin // , ,8bit ,1 2
num <= num+1'b1;
case (num)
4'd1: rx_temp_data[0] <= rs232_rx; // 0bit
4'd2: rx_temp_data[1] <= rs232_rx; // 1bit
4'd3: rx_temp_data[2] <= rs232_rx; // 2bit
4'd4: rx_temp_data[3] <= rs232_rx; // 3bit
4'd5: rx_temp_data[4] <= rs232_rx; // 4bit
4'd6: rx_temp_data[5] <= rs232_rx; // 5bit
4'd7: rx_temp_data[6] <= rs232_rx; // 6bit
4'd8: rx_temp_data[7] <= rs232_rx; // 7bit
default: ;
endcase
end
else if(num == 4'd11) begin // 1+8+1(2)=11bit /// num 11. 12!!
num <= 4'd0; // STOP ,num
rx_data_r <= rx_temp_data; // rx_data
end
end
assign rx_data = rx_data_r;
endmodule
ここでは概ねシリアルポートが1回のデータを受信する処理過程であり、データを受信した後に送信フラグビットを生成し、データの送信を開始するが、ここでいうデータキャッシュ処理には2つの解決方法があり、1つ目は16進数転送であるため、転送ごとに有効なデータは8ビットであるため、1つのレジスタreg[23:0]rx_を定義するcnt;長さ8の整数倍、シフト方式でデータを格納し、上記コードではNUMカウントが11になると1回データ転送が完了するのでnum=11のところに
rx_cnt[7:0] <= rx_data_r;
rx_cnt[23:8] <= rx_cnt[15:0] ;
cnt <= cnt+1;//
if(cnt==NUMBER)// NUMBER ,
begin
cnt<=cnt;
end
assign rx_data_out = (cnt==NUMBER)?rx_cnt:rx_data_out;
// NUMBER , ,
// 。
そして元の出力ポートassign rx_data = rx_data_r;削除して、新しい出力受信の完全なコードを書きます.
//`timescale 1ns / 1ps
module my_uart_rx(
clk,
rst_n,
rs232_rx,
rx_data,
rx_int,
start,
clk_bps,
bps_start,
rom_en,
rx_data_out
);
input clk; // 50MHz
input rst_n; //
input rs232_rx; // RS232
input clk_bps; // clk_bps
output bps_start; // ,
output[7:0] rx_data; // ,
output rx_int; // ,
output reg start;
output wire [23:0] rx_data_out;
//----------------------------------------------------------------
reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3; // ,
wire neg_rs232_rx; //
reg [23:0] rx_cnt;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
rs232_rx0 <= 1'b0;
rs232_rx1 <= 1'b0;
rs232_rx2 <= 1'b0;
rs232_rx3 <= 1'b0;
end
else begin
rs232_rx0 <= rs232_rx;
rs232_rx1 <= rs232_rx0;
rs232_rx2 <= rs232_rx1;
rs232_rx3 <= rs232_rx2;
end
end
// <20ns-40ns ( ),
// ( , )
//( 40ns )
assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0; // neg_rs232_rx
//----------------------------------------------------------------
reg bps_start_r;
reg[3:0] num; //
reg rx_int; // ,
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
bps_start_r <= 1'bz;
rx_int <= 1'b0;
end
else if(neg_rs232_rx) begin // rs232_rx
bps_start_r <= 1'b1; //
rx_int <= 1'b1; //
end
else if(num==4'd9) begin // /// num 11. 12!!
bps_start_r <= 1'b0; // ,
rx_int <= 1'b0; //
end
assign bps_start = bps_start_r;
//----------------------------------------------------------------
reg[7:0] rx_data_r; // ,
//----------------------------------------------------------------
reg[7:0] rx_temp_data; //
reg [5:0]cnt;
//assign led = (cnt==10)?1:0;
always @ (posedge clk or negedge rst_n)
if(!rst_n) begin
rx_temp_data <= 8'd0;
num <= 4'd0;
cnt<= 0;
start<=0;
rx_cnt<=24'b0;
//rx_data_out <= 384'd0;
rx_data_r <= 8'd0;
end
else if(rx_int) begin //
if(clk_bps) begin // , ,8bit ,1 2
num <= num+1'b1;
case (num)
4'd1: rx_temp_data[0] <= rs232_rx; // 0bit
4'd2: rx_temp_data[1] <= rs232_rx; // 1bit
4'd3: rx_temp_data[2] <= rs232_rx; // 2bit
4'd4: rx_temp_data[3] <= rs232_rx; // 3bit
4'd5: rx_temp_data[4] <= rs232_rx; // 4bit
4'd6: rx_temp_data[5] <= rs232_rx; // 5bit
4'd7: rx_temp_data[6] <= rs232_rx; // 6bit
4'd8: rx_temp_data[7] <= rs232_rx; // 7bit
default: ;
endcase
end
else if(num == 4'd9) begin // 1+8+1(2)=11bit /// num 11. 12!!
num <= 4'd0; // STOP ,num
rx_data_r <= rx_temp_data; // rx_data
cnt <= cnt+1;
rx_cnt[7:0] <= rx_data_r;
rx_cnt[23:8] <= rx_cnt[15:0] ;
if(cnt==NUMBER)// NUMBER ,
begin
cnt<=cnt;
start<=1;//
end
end
end
assign rx_data_out = (cnt==6'd48)?rx_cnt:rx_data_out;
endmodule
ボーレートプロファイルはネット上のコードが多いので、ここでは貼らない.