UARTの受信から実装しました。
module UART_RX(
input rxRST,
input rxCLK,
input rxRXD,
output reg rxDATAREADY,
output reg [7:0] rxDATA
);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
reg shift, clr_bitcnt, enb_bitcnt, clr_sampcnt, enb_sampcnt; reg [15:0] cnt; reg [3:0] bitcnt; reg [1:0] sampcnt; reg [9:0] shiftreg; reg stat, nexstat; always @(posedge rxCLK) begin if(rxRST) begin stat <= 1'b0; cnt <= 16'h0; bitcnt <= 4'h0; sampcnt <= 2'h0; shiftreg <= 10'h0; end else begin cnt <= cnt + 16'h1; if(cnt >= 4) begin //baud rate = 5M cnt <= 16'h0; stat <= nexstat; if(shift) shiftreg <= {rxRXD, shiftreg[9:1]}; if(clr_bitcnt) bitcnt <= 4'h0; if(enb_bitcnt) bitcnt <= bitcnt + 4'h1; if(clr_sampcnt) sampcnt <= 2'h0; if(enb_sampcnt) sampcnt <= sampcnt + 2'h1; end end end always @(posedge rxCLK) begin shift <= 1'h0; clr_sampcnt <= 1'h0; enb_sampcnt <= 1'h0; clr_bitcnt <= 1'h0; enb_bitcnt <= 1'h0; nexstat <= 1'h0; rxDATAREADY <= 1'h0; case(stat) 0: begin if(rxRXD) nexstat <= 1'h0; else begin nexstat <= 1'h1; clr_bitcnt <= 1'h1; clr_sampcnt <= 1'h1; end end 1: begin nexstat <= 1'h1; if(sampcnt == 1) shift <= 1'h1; if(sampcnt == 3) begin if(bitcnt == 9) begin nexstat <= 1'h0; rxDATAREADY <= 1'h1; rxDATA <= shiftreg[8:1]; end enb_bitcnt <= 1'h1; clr_sampcnt <= 1'h1; end else enb_sampcnt <= 1'h1; end default: nexstat <= 1'h0; endcase end |
endmodule
一つ目のループは、cntで100MHzのクロックをカウントし、受信信号のビット幅を4分の1にするタイミング信号を作成します。 シミュレーションの時間を短くするためにBaud rateは、5MHzにしました。 bitcntは、受信信号を何ビット目かをカウントし、sampcntは、4分割したビットのどの位置かをカウントするカウンタです。
sampcntが1の時、shiftがhighになるのでそのタイミングでRXDをshiftregisterに取り込みます。
スタートビットが検知されると、smpcntとbitcntが有効になり、smpcntは、ビット幅4分の1で毎回カウントされ、bitcntはsmpcntが3になった時にカウントされます。
2つ目のループは、ステートマシンで、stat=0でアイドリング、stat=1で、sampcntの判定、bitcntの判定を行っています。
module sim_uart_rx;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
localparam STEP = 10; reg rst; reg clk; reg rxd; wire dataready; wire [7:0] data; UART_RX UART_RX( .rxRST (rst), .rxCLK (clk), .rxRXD (rxd), .rxDATAREADY (dataready), .rxDATA (data) ); always begin clk = 0; #(STEP/2); clk = 1; #(STEP/2); end initial begin rxd = 1; rst = 0; #(STEP*10); rst = 1; #(STEP*10); rst = 0; #(STEP*10); rxd = 0; //Start bit #(STEP*20); rxd = 1; #(STEP*20); rxd = 0; #(STEP*20); rxd = 0; #(STEP*20); rxd = 1; #(STEP*20); rxd = 0; #(STEP*20); rxd = 1; #(STEP*20); rxd = 0; #(STEP*20); rxd = 1; #(STEP*20); rxd = 1; //Stop bit #(STEP*40); $stop; end |
endmodule
rxdがlowになった時に、ステートが1に代わって、sampcntがスタートし、sampcntが3になるとbitcntがスタートしています。
bitcntが9になったところで、dataが”a9″になって、datareadyがhighになりました。
論理合成はしていませんが、送信側を作ってからまとめて論理合成したいと思います。