OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [XUPV5-LX110T_SoC/] [MIPS32-Pipelined-Hw/] [src/] [UART/] [uart_bootloader_v1.v] - Rev 7

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Grant Ayers (ayers@cs.utah.edu)
// 
// Create Date:    09:59:05 05/24/2010 
// Design Name: 
// Module Name:    uart_bootloader 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description:
//       Implements the XUM bootloader protocol over a serial port (115200 8N1).
//       The protocol is as follows:
//
//       1. Programmer sends 'XUM' ascii bytes
//       2. Programmer sends a number indicating how many 32-bit data words it
//          has to send, minus 1. (For example, if it has one 32-bit data word,
//          this number will be 0.) The size of this number is 18 bits.
//          This means the minimum transmission size is 1 word (32 bits), and
//          the maximum transmission size is 262144 words (exactly 1MB).
//          This 18-bit number is sent in three bytes, and the six most
//          significant bits of the first byte must be 0.
//       3. The FPGA sends back the third size byte from the programmer, allowing
//          the programmer to determine if the FPGA is listening and conforming
//          to the XUM boot protocol.
//       4. The programmer sends another 18-bit number indicating the starting
//          offset in memory where the data should be placed. Normally this will
//          be 0. This number is also sent in three bytes, and the six most
//          significant bits of the first byte are ignored.
//       5. The programmer sends the data. A copy of each byte that it sends will
//          be sent back to the programmer from the FPGA, allowing the programmer
//          to determine if all of the data was transmitted successfully.
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module uart_bootloader(
   input clock,                  // 100Mhz
   input reset,                  // System-wide global reset
   input RxD,                    // UART data from computer
   output TxD,                   // UART data to computer
   output resetCPU,              // Reset CPUs' PCs to start execution at 0x0
   output reg writeMem = 0,      // Write command to instruction memory
   output reg [17:0] addrMem = 0, // address to instruction memory
   output reg [31:0] dataMem = 0 // 32-bit data words of instruction memory
   );
 
   localparam [3:0]  HEAD_1=0, HEAD_2=1, HEAD_3=2, SIZE_1=3, SIZE_2=4, SIZE_3=5, OFST_1=6, OFST_2=7,
                     OFST_3=8, ADDRSET=9, DATA_1=10, DATA_2=11, DATA_3=12, DATA_4=13, ADDRINC=14;
 
   /* UART Signals */
   reg uart_write = 0;
   reg uart_read = 0;
 
   wire [7:0] uart_rx_data;
   wire [7:0] uart_tx_data = uart_rx_data;
   wire uart_rx_data_ready;
 
   reg [17:0] size = 0;       // Number of 32-bit words to expect
   reg [17:0] offset = 0;     // Starting address to store words
   reg [17:0] rx_count = 0;   // Number of 32-bit words received so far
 
   reg [3:0] state = HEAD_1;
 
   // The CPU(s) is continuously reset while memory is being replaced.
   assign resetCPU = ((state!=HEAD_1) && (state!=HEAD_2) && (state!=HEAD_3) && (state!=SIZE_1));
 
   always @(posedge clock) begin
      if (reset) begin
         state <= HEAD_1;
         uart_read <= 0;
         uart_write <= 0;
         writeMem <= 0;
         rx_count <= 0;
      end
      else begin
         uart_read <= uart_rx_data_ready & ((state!=ADDRSET) && (state!=ADDRINC));
         uart_write <= uart_rx_data_ready & ((state==SIZE_3) || (state==DATA_1) || (state==DATA_2) || (state==DATA_3) || (state==DATA_4));
         writeMem <= uart_rx_data_ready & (state == DATA_4);
         rx_count <= (state == HEAD_1) ? 0 : ((state == ADDRINC) ? rx_count + 1 : rx_count);
         case (state)
            HEAD_1:  begin
                        if (uart_rx_data_ready) begin
                           state <= (uart_rx_data == 8'h58) ? HEAD_2 : HEAD_1;   // 'X'
                        end
                        else begin
                           state <= HEAD_1;
                        end
                     end
            HEAD_2:  begin
                        if (uart_rx_data_ready) begin
                           state <= (uart_rx_data == 8'h55) ? HEAD_3 : HEAD_1;   // 'U'
                        end
                        else begin
                           state <= HEAD_2;
                        end
                     end
            HEAD_3:  begin
                        if (uart_rx_data_ready) begin
                           state <= (uart_rx_data == 8'h4D) ? SIZE_1 : HEAD_1;   // 'M'
                        end
                        else begin
                           state <= HEAD_3;
                        end
                     end
            SIZE_1:  begin
                        if (uart_rx_data_ready) begin
                           state <= (uart_rx_data[7:2] == 6'b000000) ? SIZE_2 : HEAD_1;   // 6 leading 0s
                           size[17:16] <= uart_rx_data[1:0];
                        end
                        else begin
                           state <= SIZE_1;
                        end
                     end
            SIZE_2:  begin
                        state <= (uart_rx_data_ready) ? SIZE_3 : SIZE_2;
                        size[15:8] <= (uart_rx_data_ready) ? uart_rx_data : size[15:8];
                     end
            SIZE_3:  begin
                        state <= (uart_rx_data_ready) ? OFST_1 : SIZE_3;
                        size[7:0] <= (uart_rx_data_ready) ? uart_rx_data : size[7:0];
                     end
            OFST_1:  begin
                        state <= (uart_rx_data_ready) ? OFST_2 : OFST_1;
                        offset[17:16] <= (uart_rx_data_ready) ? uart_rx_data[1:0] : offset[17:16];
                     end
            OFST_2:  begin
                        state <= (uart_rx_data_ready) ? OFST_3 : OFST_2;
                        offset[15:8] <= (uart_rx_data_ready) ? uart_rx_data : offset[15:8];
                     end
            OFST_3:  begin
                        state <= (uart_rx_data_ready) ? ADDRSET : OFST_3;
                        offset[7:0] <= (uart_rx_data_ready) ? uart_rx_data : offset[7:0];
                     end
            ADDRSET: begin
                        state <= DATA_1;
                        addrMem <= offset;
                     end
            DATA_1:  begin
                        state <= (uart_rx_data_ready) ? DATA_2 : DATA_1;
                        dataMem[31:24] <= (uart_rx_data_ready) ? uart_rx_data : dataMem[31:24];
                     end
            DATA_2:  begin
                        state <= (uart_rx_data_ready) ? DATA_3 : DATA_2;
                        dataMem[23:16] <= (uart_rx_data_ready) ? uart_rx_data : dataMem[23:16];
                     end
            DATA_3:  begin
                        state <= (uart_rx_data_ready) ? DATA_4 : DATA_3;
                        dataMem[15:8] <= (uart_rx_data_ready) ? uart_rx_data : dataMem[15:8];
                     end
            DATA_4:  begin
                        state <= (uart_rx_data_ready) ? ADDRINC : DATA_4;
                        dataMem[7:0] <= (uart_rx_data_ready) ? uart_rx_data : dataMem[7:0];
                     end
            ADDRINC:   begin
                        addrMem <= addrMem + 1;
                        state <= (rx_count == size) ? HEAD_1 : DATA_1;
                     end
            default: state <= HEAD_1;
         endcase
      end
   end
 
 
   uart_min uart (
      .clock      (clock), 
      .reset      (reset), 
      .write      (uart_write), 
      .data_in    (uart_tx_data), 
      .read       (uart_read), 
      .data_out   (uart_rx_data), 
      .data_ready (uart_rx_data_ready), 
      .RxD        (RxD), 
      .TxD        (TxD)
   );
 
endmodule
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.