`timescale 1ns / 1ps module main( CLK_50M, LED, SW, RS232_DCE_RXD, RS232_DCE_TXD, SD_A, SD_BA, SD_CK_N, SD_CK_P, SD_CKE, SD_CS, SD_RAS, SD_CAS, SD_WE, SD_ODT, SD_LDM, SD_UDM, SD_LDQS_N, SD_LDQS_P, SD_UDQS_N, SD_UDQS_P, SD_DQ ); input CLK_50M; output [7:0] LED; input [3:0] SW; input RS232_DCE_RXD; output RS232_DCE_TXD; output [15:0] SD_A; output [2:0] SD_BA; output SD_CK_N; output SD_CK_P; output SD_CKE; output SD_CS; output SD_RAS; output SD_CAS; output SD_WE; output SD_ODT; output SD_LDM; output SD_UDM; inout SD_LDQS_N; inout SD_LDQS_P; inout SD_UDQS_N; inout SD_UDQS_P; inout [15:0] SD_DQ; wire clk; wire txd; wire rxd; assign clk = CLK_50M; assign RS232_DCE_TXD = txd; assign rxd = RS232_DCE_RXD; reg reset; reg [31:0] address; reg [31:0] data; // serial com. reg [7:0] tx_tch; reg tx_cs; wire tx_busy; tx tx(~clk, txd, tx_tch, tx_cs, tx_busy, reset); wire [7:0] rx_rch; wire rx_rcv; rx rx(~clk, rxd, rx_rch, rx_rcv, reset); reg rx_rcv_old; reg [7:0] rcv_cmd; reg [63:0] rcv_data; // SDRAM com. reg sdram_cs; reg sdram_wr; reg [31:0] sdram_address; reg [31:0] sdram_idata; wire [31:0] sdram_odata; wire sdram_data_en; wire sdram_busy; wire [15:0] sd_a; wire [2:0] sd_ba; wire sd_ck_n; wire sd_ck_p; wire sd_cke; wire sd_cs; wire sd_ras; wire sd_cas; wire sd_we; wire sd_odt; wire sd_ldm; wire sd_udm; assign SD_A = sd_a; assign SD_BA = sd_ba; assign SD_CK_N = sd_ck_n; assign SD_CK_P = sd_ck_p; assign SD_CKE = sd_cke; assign SD_CS = sd_cs; assign SD_RAS = sd_ras; assign SD_CAS = sd_cas; assign SD_WE = sd_we; assign SD_ODT = sd_odt; assign SD_LDM = sd_ldm; assign SD_UDM = sd_udm; wire sd_nz; wire sd_oldqs; wire sd_oudqs; wire [15:0] sd_odq; assign SD_LDQS_N = sd_nz ? ~sd_oldqs : 1'bZ; assign SD_LDQS_P = sd_nz ? sd_oldqs : 1'bZ; assign SD_UDQS_N = sd_nz ? ~sd_oudqs : 1'bZ; assign SD_UDQS_P = sd_nz ? sd_oudqs : 1'bZ; assign SD_DQ = sd_nz ? sd_odq : 16'bZZZZZZZZZZZZZZZZ; ddr2 ddr2( ~clk, reset, sdram_cs, sdram_wr, sdram_address, sdram_idata, sdram_odata, sdram_data_en, sdram_busy, sd_a, sd_ba, sd_ck_n, sd_ck_p, sd_cke, sd_cs, sd_ras, sd_cas, sd_we, sd_odt, sd_ldm, sd_udm, sd_nz, SD_LDQS_P, SD_UDQS_P, SD_DQ, sd_oldqs, sd_oudqs, sd_odq ); // state machine reg start; reg start2; reg [3:0] status; parameter STATUS_NOINIT = 4'd0; parameter STATUS_START = 4'd1; parameter STATUS_INITIALIZE = 4'd2; parameter STATUS_INITEND = 4'd3; parameter STATUS_IDLE = 4'd4; parameter STATUS_READ_START = 4'd5; parameter STATUS_WRITE_START = 4'd6; parameter STATUS_READING = 4'd7; parameter STATUS_WRITING = 4'd8; parameter STATUS_SEND = 4'd9; parameter STATUS_SENDING = 4'd10; parameter STATUS_SENDED = 4'd11; parameter STATUS_UNKNOWN = 4'b1111; parameter START_WAIT = 5000000; // 100ms parameter INITEND_WAIT = 5000000; // 100ms // parameter START_WAIT = 50000000; // 1s // parameter INITEND_WAIT = 50000000; // 1s reg [31:0] wait_count; reg [4:0] send_count; reg [127:0] send_ch; // LED assign LED[7] = SW[0] ? rx_rcv : rx_rch[7]; assign LED[6] = SW[0] ? rx_rcv_old : rx_rch[6]; assign LED[5] = SW[0] ? rxd : rx_rch[5]; assign LED[4] = SW[0] ? reset : rx_rch[4]; assign LED[3] = SW[0] ? status[3] : rx_rch[3]; assign LED[2] = SW[0] ? status[2] : rx_rch[2]; assign LED[1] = SW[0] ? status[1] : rx_rch[1]; assign LED[0] = SW[0] ? status[0] : rx_rch[0]; // functions function [3:0] a2b4; input [7:0] a; begin if ((a >= 8'h30) && (a <= 8'h39)) a2b4 = (a - 8'h30); else if ((a >= 8'h61) && (a <= 8'h66)) a2b4 = (a - 8'h57); else if ((a >= 8'h41) && (a <= 8'h46)) a2b4 = (a - 8'h37); else a2b4 = 8'd0; end endfunction function [7:0] a2b8; input [15:0] a; begin a2b8[7:4] = a2b4(a[15:8]); a2b8[3:0] = a2b4(a[ 7:0]); end endfunction function [7:0] b2a4; input [3:0] b; begin if (b <= 4'd9) begin b2a4 = b + 8'h30; end else begin b2a4 = b + 8'h57; end end endfunction function [15:0] b2a8; input [7:0] b; begin b2a8[15:8] = b2a4(b[7:4]); b2a8[ 7:0] = b2a4(b[3:0]); end endfunction // main always @(posedge clk) begin if (start == start2) begin start <= ~start; status <= STATUS_NOINIT; end else begin case (status) STATUS_NOINIT: begin wait_count <= 0; status <= STATUS_START; end STATUS_START: begin if (wait_count < START_WAIT) begin wait_count <= wait_count + 1; end else begin reset <= 1'b1; tx_cs <= 1'b0; sdram_cs <= 1'b0; status <= STATUS_INITIALIZE; end end STATUS_INITIALIZE: begin reset <= 1'b0; wait_count <= 0; status <= STATUS_INITEND; end STATUS_INITEND: begin if (wait_count < INITEND_WAIT) begin wait_count <= wait_count + 1; end else begin // status <= STATUS_IDLE; status <= STATUS_SEND; send_count <= 5; send_ch[ 7: 0] <= 8'h52; // 'R' send_ch[15: 8] <= 8'h45; // 'E' send_ch[23:16] <= 8'h41; // 'A' send_ch[31:24] <= 8'h44; // 'D' send_ch[39:32] <= 8'h59; // 'Y' end end STATUS_IDLE: begin if (rx_rcv_old != rx_rcv) begin rx_rcv_old <= rx_rcv; case (rx_rch) 8'h24: // '$' begin rcv_cmd <= 0; rcv_data <= 0; status <= STATUS_SEND; send_count <= 1; send_ch[7:0] <= rx_rch; end 8'h2b: // '+' begin // $Rabcd3210+ (read 4byte) // $Wabcd3210aabbccdd+ (write 4byte) case (rcv_cmd) 8'h52: // 'R' begin address[31:0] <= rcv_data[31:0]; status <= STATUS_READ_START; end 8'h57: // 'W' begin address[31:0] <= rcv_data[63:32]; data[31:0] <= rcv_data[31: 0]; status <= STATUS_WRITE_START; end default: begin status <= STATUS_SEND; send_count <= 3; send_ch[ 7: 0] <= 8'h45; // 'E' send_ch[15: 8] <= 8'h52; // 'R' send_ch[23:16] <= 8'h52; // 'R' end endcase end default: begin status <= STATUS_SEND; send_count <= 1; send_ch[7:0] <= rx_rch; if (rcv_cmd == 8'h00) begin rcv_cmd <= rx_rch; end else begin rcv_data[63: 4] <= rcv_data[59:0]; rcv_data[ 3: 0] <= a2b4(rx_rch); end end endcase end end STATUS_READ_START: begin if (sdram_busy == 1'b0) begin sdram_cs <= 1'b1; sdram_wr <= 1'b0; sdram_address <= address; status <= STATUS_READING; end end STATUS_WRITE_START: begin if (sdram_busy == 1'b0) begin sdram_cs <= 1'b1; sdram_wr <= 1'b1; sdram_address <= address; sdram_idata <= data; status <= STATUS_WRITING; end end STATUS_READING: begin if (sdram_data_en) begin sdram_cs <= 1'b0; sdram_wr <= 1'b0; sdram_address <= 0; sdram_idata <= 0; data <= sdram_odata; status <= STATUS_SEND; send_count <= 9; send_ch[ 7: 0] <= 8'h2b; // '+' send_ch[23: 8] <= b2a8(sdram_odata[31:24]); send_ch[39:24] <= b2a8(sdram_odata[23:16]); send_ch[55:40] <= b2a8(sdram_odata[15: 8]); send_ch[71:56] <= b2a8(sdram_odata[ 7: 0]); end end STATUS_WRITING: begin if (sdram_busy == 1'b0) begin sdram_cs <= 1'b0; sdram_wr <= 1'b0; sdram_address <= 0; sdram_idata <= 0; status <= STATUS_SEND; send_count <= 3; send_ch[ 7: 0] <= 8'h2b; // '+' send_ch[15: 8] <= 8'h4f; // 'O' send_ch[23:16] <= 8'h4b; // 'K' end end STATUS_SEND: begin if (send_count == 0) begin status <= STATUS_IDLE; end else if (tx_busy == 1'b0) begin send_count <= send_count - 1; send_ch[119:0] <= send_ch[127:8]; tx_tch <= send_ch[7:0]; tx_cs <= 1'b1; status <= STATUS_SENDING; end end STATUS_SENDING: begin if (tx_busy == 1'b1) begin tx_cs <= 1'b0; status <= STATUS_SENDED; end end STATUS_SENDED: begin if (tx_busy == 1'b0) status <= STATUS_SEND; end default: begin status <= STATUS_UNKNOWN; end endcase end end endmodule