具体的にコーディングします。
ステートマシンを使って制御します。 状態は、PCからコマンドが送られてくるのを待機(NOR)、ADCからメモリへ書き込み(WCNT)、メモリから読みだして、UARTで送信(RCNT)の3つです。 ソースコードには、余計な状態が記載されていますが、実際に使用しているのは3つだけです。
NORは、UART_RXでデータを受信してコマンドレジスタ(cmdreg)に入力するという動作を繰り返します。コマンドレジスタの内容が”00000001″になると、次のステートWCNTに移行します。
WCNTでは、ADCからの10bitの符号付データを16bit幅でメモリに書き込みます。 この時、普通はビット拡張が必要ですが、ビット拡張がなくても正常に動作しているようです。 メモリの書き込みアドレスが255になると、次のステートRCNTに移行します。
RCNTでは、UART_TXからのtxLOADをクロックとして、メモリから8ビットのデータを読み出しUART_TXを使ってデータをPCに送ります。
実際のソースコードです。
module ADC2020(
input MRST,
input MCLK,
output STB,
input signed [9:0] ADC_DATA,
output TXD,
input RXD
);
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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
wire clk80; //80MHzクロック wire w_clk, r_clk; //書き込みクロック、読み出しクロック wire wen; //書き込み可 wire [7:0] rDATA; wire rxstb, start; wire signed [15:0] data_in; wire [7:0] data_out; reg txstart; reg [7:0] tDATA; reg [7:0] data; reg [7:0] w_add; //256 reg [8:0] r_add; //512 reg [7:0] cmdreg = 8'b00000000; reg [3:0] cur0, nex0; parameter NOR = 4'b0000, WCNT = 4'b0001, RSTA = 4'b0010, RCNT = 4'b0011, STP = 4'b0100; CLK80 CLK80(.clk_in1(MCLK), .clk_out1(clk80)); UART_RX UART_RX(.rxRST(MRST), .rxCLK(clk80), .rxRXD(RXD), .rxDATAREADY(rxstb), .rxDATA(rDATA)); UART_TX UART_TX(.txDATA(tDATA), .txRST(MRST), .txCLK(clk80), .txSTART(txstart), .txLOAD(r_clk), .txTXD(TXD)); Buffer0 Bbuffer0(.clka(w_clk), .wea(wen), .addra(w_add), .dina(data_in), .clkb(r_clk), .addrb(r_add), .doutb(data_out)); assign data_in = ADC_DATA; assign STB = ~clk80; assign wen = (cur0 == WCNT); assign w_clk = clk80 & wen; assign start = (cmdreg == 8'b00000001); always @(posedge clk80 or posedge MRST) begin if(MRST) cur0 <= NOR; else cur0 <= nex0; end always @(negedge w_clk or posedge MRST) begin if(MRST) w_add <= 0; else w_add <= w_add + 1; end always @(negedge r_clk or posedge MRST) begin if(MRST) r_add <= 0; else r_add <= r_add + 1; end always @(posedge r_clk) begin tDATA <= data_out; end always @(posedge rxstb) begin cmdreg <= rDATA; end always @(cur0 or start or w_add or r_add) begin txstart <= 0; case(cur0) NOR: if(start) nex0 <= WCNT; else nex0 <= NOR; WCNT: if(w_add == 8'b11111111) nex0 <= RCNT; else nex0 <= WCNT; RCNT: begin txstart <= 1; if(r_add == 9'b111111111) nex0 <= NOR; else nex0 <= RCNT; end default: nex0 <= NOR; endcase end |
endmodule