`timescale 1ns/1ps module top( input clock, // system clock input reset, // BTNR input version, // BTNU input adc_n, adc_p, // VCAUX 6, P and N input [15:0] sw, // slide switches output [15:0] led, // 16 onboard LEDs above the switches output [6:0] segment, // 4 digit LED display output dp, // "." next to each LED digit output [3:0] digit, // 7-segment display anode select output reg [7:0] JB, // PMOD JB for debugging output [7:0] JA, // PMOD JA for debugging input rx, // UART receive output tx // UART transmit ); parameter VERSION = 'h0011; // // generate a 25MHz and 8MHz clock for the UART and FIFO // wire locked, clock25, clock8; clocks MYCLOCKS ( .reset(reset), .clk_in1(clock), .locked(locked), .clk_out1(clock25), .clk_out2(clock8) ); // // divide clock8 by 8 to get the 1MHz ADC clock // reg [2:0] count8; always @ (posedge clock8) count8 <= count8 + 1; wire clock1; BUFG clk1buf (.I(count8[2]), .O(clock1)); // // next drive the 4 7-segment displays // wire [15:0] display_this; display4 DISPLAY ( .clk100(clock), .number(display_this), .digit(digit), .segments(segment), .period(dp) ); // // instantiate the UART receiver. run with the 50MHz clock so that // we can run the transmitter FSM at 100MHz and not get lost // wire dv; wire [7:0] rx_data; uart_rx RECEIVER ( .i_Clocks_per_Bit('d25), .i_Clock(clock25), .i_Reset(reset), .i_Rx_Serial(rx), // tied to FPGA rx output .o_Rx_DV(dv), .o_Rx_Byte(rx_data) ); // // instantiate a fifo for the UART receiving from the RPi // tie rx_wr_en to dv so that we can have the fifo write clock // always going. read will be controlled by the read/write FSM // in the controller.v module which has clocks running at 1MHz. // wire rx_wr_en = dv; wire rx_full, rx_empty; wire rx_rd_en; wire [8:0] rx_dout; rxfifo FIFO_RX ( // this fifo is 9 bits wide .rst(reset), .wr_clk(clock25), .rd_clk(clock1), .din({1'b0,rx_data}), // remember, 9 bits in! .wr_en(rx_wr_en), .rd_en(rx_rd_en), .dout(rx_dout), // and 9 bits out .full(rx_full), .empty(rx_empty) ); // // instantiate the UART transmitter // wire tx_active, tx_done; wire do_transmit; wire [7:0] transmit_byte; uart_tx TRANSMITTER ( .i_Clocks_per_Bit('d25), .i_Clock(clock25), .i_Reset(reset), .i_Tx_DV(do_transmit), .i_Tx_Byte(transmit_byte), .o_Tx_Active(tx_active), .o_Tx_Serial(tx), // tied to FPGA tx output .o_Tx_Done(tx_done) ); // // note that the OUT FSM in controller waits for tx_done, which comes from uart_tx which // runs with a 25HMz clock whereas this FSM here runs with a 1MHz clock // (so that it can be in sync with the data fifo). so we will need to // stretch out the tx_done signal, which is only 40ns wide, to make it // 1us wide so the OUT FSM doesn't miss it // wire tx_done_1us; stretch TX_STRETCH ( .clock(clock25),.reset(reset),.ticks('d25),.sigin(tx_done),.sigout(tx_done_1us) ); // // here is the XADC block // wire [6:0] daddr_in = 7'h16; wire adc_ready, isbusy, adc_data_ready, eos_out, alarm; wire [15:0] adc_data; wire [4:0] channel_out; myxadc XADC_INST ( .daddr_in(7'h16), // specifies vcaux6 pints to digitize .dclk_in(clock), // 50MHz clock .den_in(adc_ready), // tied to adc_ready, tells adc to convert, tieing causes continuous conversions .di_in(16'h0), // to set the data to something, not used here .dwe_in(1'b0), // set to enable writing to di_in, which we don't want to do .vauxp6(adc_p), // positive input to digitize .vauxn6(adc_n), // negative input to digitize .busy_out(isbusy), // tells you the adc is busy converting .channel_out(channel_out[4:0]), // for using more than 1 channel, tells you which one. not used here .do_out(adc_data), // adc value from conversion .drdy_out(adc_data_ready), // tells you valid data is ready to be latched .eoc_out(adc_ready), // specifies that the ADC is ready (conversion complete) .eos_out(eos_out), // specifies that conversion sequence is complete .alarm_out(alarm), // OR's output of all internal alarms, not used here .vp_in(1'b0), // dedicated analog input pair for differential, tied to 0 if not used .vn_in(1'b0) ); // // Wait for XADC to tell you something is ready to latch, and latch it into the // r_adc_data bus. Note this means continuous latching // reg [15:0] r_adc_data; always @ (posedge adc_data_ready) begin if (reset) r_adc_data <= 16'h0; else r_adc_data <= adc_data; end // // make a ~1Hz clock so we can run the LED display slower // reg [19:0] counter; reg [15:0] s_adc_data; always @ (posedge clock1) begin if (reset) counter <= 0; else counter <= counter + 1; end wire clock_1hz = counter[19]; always @ (posedge clock_1hz) s_adc_data <= r_adc_data; assign display_this = version ? VERSION : s_adc_data; // // instantiate our data fifo next // wire triggered; // comes out of the controller wire [17:0] din = {triggered,1'b0,r_adc_data}; // feed this directly into the FIFO data input wire [17:0] dout; wire [12:0] fifo_adc_out = {dout[17],dout[15:4]}; // send to controller the ADC bits and whether this triggered wire wr_en; wire rd_en, fifo_full, fifo_empty, wr_rst_busy, rd_rst_busy; wire [15:0] fifo_data_count; myfifo DATA_FIFO ( .rst(reset), .wr_clk(clock1), .rd_clk(clock1), .din(din), .wr_en(wr_en), .rd_en(rd_en), .dout(dout), .full(fifo_full), .empty(fifo_empty), .rd_data_count(fifo_data_count), .wr_rst_busy(wr_rst_busy), .rd_rst_busy(rd_rst_busy) ); // // now make a state machine to deal with transmitting 2 bytes at a // time, including the FIFO value that is present. // reg [2:0] tx_state; // 8 states so 3 bits will do localparam [2:0] TX_IDLE=0, TX_BYTE1=1, TX_DO1=2, TX_WAIT1=3, TX_BYTE2=4, TX_DO2=5, TX_WAIT2=6, TX_DONE=7; reg doit; wire [15:0] transmit_word; wire begin_transfer; reg [7:0] tx_data; always @ (posedge clock25) begin if (reset) begin tx_state <= TX_IDLE; doit <= 0; tx_data <= 0; end else case (tx_state) TX_IDLE: begin // // wait for begin_transfer to start // if (begin_transfer) tx_state <= TX_BYTE1; else tx_state <= TX_IDLE; doit <= 0; tx_data <= 0; end TX_BYTE1: begin // // latch the first byte of the transmit_word // tx_data <= transmit_word[7:0]; tx_state <= TX_DO1; end TX_DO1: begin // // turn on uart_tx // doit <= 1; tx_state <= TX_WAIT1; end TX_WAIT1: begin // // turn off doit and wait for uart_tx to finish // doit <= 0; if (tx_done) tx_state <= TX_BYTE2; else tx_state <= TX_WAIT1; end TX_BYTE2: begin // // latch the 2nd byte to transfer // tx_data <= transmit_word[15:8]; tx_state <= TX_DO2; end TX_DO2: begin // // turn on uart_tx // doit <= 1; tx_state <= TX_WAIT2; end TX_WAIT2: begin // // wait for the 2nd byte to finish begin sent // doit <= 0; if (tx_done) tx_state <= TX_DONE; else tx_state <= TX_WAIT2; end TX_DONE: begin // // wait for begin_transfer to go away // if (do_transmit) tx_state <= TX_DONE; else tx_state <= TX_IDLE; end default: begin tx_state <= TX_IDLE; end endcase end assign do_transmit = doit; assign transmit_byte = tx_data; // // instantiate the controller that handles uart rx, and the data fifo // wire [31:0] c_debug; controller CONTROL ( .clock(clock1), .reset(reset), .rx_fifo_empty(rx_empty), .rx_fifo_data(rx_dout[7:0]), .rx_fifo_rd(rx_rd_en), .tx_done(tx_done_1us), .tx_transmit(begin_transfer), .tx_out(transmit_word), .firmware_version(VERSION), .test_vector(sw), .r_adc_data(r_adc_data), .data_fifo_rd_en(rd_en), .data_fifo_wr_en(wr_en), .data_fifo_empty(fifo_empty), .data_fifo_full(fifo_full), .data_fifo_data(fifo_adc_out), .data_fifo_count(fifo_data_count), .led(led), .triggered(triggered), .debug(c_debug) ); // // use the output ports JA and JB, and the slide switches to get different // debug data for the logic analyzer // // c_debug: // // // 2:0 rx_state // 3 outgoing_done // 4 incoming_done // 5 do_outgoing // 6 do_incoming // 11:7 rx_instructions // 15:12 in_state // 19:16 out_state // 20 tx_transmit // 21 out_read_fifo which is for the ADC fifo // 22 in_read_fifo which is for the rx fifo // 23 do_read_fifo also for the rx fifo // 26:24 f_state // 27 df_wr_en // 28 df_rd_en // 29 count_fill // 30 data_fifo_empty // 31 data_fifo_full assign JA = {rx_rd_en,rx_empty,begin_transfer,tx_done,tx,dv,rx,clock25}; always @* case (sw[15:14]) 2'b00: JB = {c_debug[15:12],c_debug[6],c_debug[2:0]}; // in_state,do_incoming,rx_state 2'b01: JB = {c_debug[19:16],c_debug[5],c_debug[2:0]}; // out_state,do_outgoing,rx_state 2'b10: JB = c_debug[31:24]; // data_fifo_full,data_fifo_empty,count_fill,rd_en,wr_en,f_state 2'b11: JB = {c_debug[6],c_debug[5],c_debug[11:7],clock1}; //do_in,do_out,rx_instructions,clock endcase endmodule