Issue with Remote Update State Machine
While looking for sample designs invoking the RSU via a state machine, I came across an older intel/altera design. The code is designed to repeatedly ping-pong between the factory image and the application image; however, I've gotten varied results. The FPGA will boot the factory image, then use the RSU to boot the application image successfully. When the application image tries return to the factory image, the FPGA does not successfully load and becomes completely unresponsive until reprogrammed. For my design we are using a S25FL256 to hold the SOF files.
The Code for each state machine is below and attached to this post:
Factory_image.v
module c10rsu //factory image #( parameter APP_IMAGE_START = 32'h00800000, //copy this address directly from EPCQ datasheet parameter TIME_BETWEEN_STATES = 32'h01777777 ) // BLOCK START ADDRESS END ADDRESS // // Page_0 0x00000000 0x007FFFFF (0x006C16A3) Sector 0 to 127 // Page_1 0x00800000 0x0100FFFF (0x00EC16A3) Sector 128 to 255 ( input wire c10_clk50m, output [3:0] led ); // wire clk40; reg [31:0] data_in; reg [ 2:0] param; reg read_param; reg reconfig; reg reset = 1'b0; wire reset_timer = 1'b0; reg write_param = 1'b0; wire busy; wire [31:0] data_out; reg [31:0] count = 32'b0; reg [ 2:0] state = 3'b000; wire pof_error; //The count LED serves as a heartbeat, to see the design is functioning assign led[3] = (count[21] ); //LEDs to show the state assign led[2:0] = ~state[2:0]; //State Machine: //0: Reset the remote system update circuitry //1: Release the reset //2: Empty State //3: Set LEDs to indicate why we are in state //4: Set the address for the application image //5: Disable the watchdog timer //6: Boot the application image //7: Hold always @(posedge c10_clk50m) begin case (state) //Reset the remote system update circuitry 3'b000: begin count <= count + 1; reset <= 1'b1; param <= 3'b000; read_param <= 1'b0; data_in <= data_in; write_param <= 1'b0; reconfig <= 1'b0; if (count==TIME_BETWEEN_STATES) begin state <= 3'b001; count <= 32'b0; end end //Release the reset 3'b001: begin count <= count + 1; reset <= 1'b0; param <= 3'b000; read_param <= 1'b0; data_in <= data_in; write_param <= 1'b0; reconfig <= 1'b0; if (count==TIME_BETWEEN_STATES) begin state <= 3'b010; count <= 32'b0; end end //Empty state 3'b010: begin count <= count + 1; if (count==TIME_BETWEEN_STATES) begin state <= 3'b011; count <= 32'b0; end end //Set LEDs to indicate why we are in state and set AnF to 1 3'b011: begin count <= count + 1; reset <= 1'b0; param <= 3'b101; read_param <= 1'b0; reconfig <= 1'b0; data_in <= 32'h00000001; if (count[29]==1'b0) write_param <= 1'b1; else write_param <= 1'b0; if (count==TIME_BETWEEN_STATES) begin state <= 3'b100; count <= 32'b0; end end //Set the address for the application image 3'b100: begin count <= count + 1; reset <= 1'b0; param <= 3'b100; read_param <= 1'b0; reconfig <= 1'b0; data_in <= APP_IMAGE_START; if (count[29]==1'b0) write_param <= 1'b1; else write_param <= 1'b0; if (count==TIME_BETWEEN_STATES) begin state <= 3'b101; count <= 32'b0; end end //Disable the watchdog timer 3'b101: begin count <= count + 1; reset <= 1'b0; param <= 3'b011; read_param <= 1'b0; reconfig <= 1'b0; data_in <= 32'h00000000; if (count[29]==1'b0) write_param <= 1'b1; else write_param <= 1'b0; if (count==TIME_BETWEEN_STATES) begin state <= 3'b110; count <= 32'b0; end end //Boot the application image 3'b110: begin count <= count + 1; reset <= 1'b0; param <= param; //output read_param <= 1'b0; data_in <= data_in; write_param <= 1'b0; reconfig <= 1'b1; if (count==TIME_BETWEEN_STATES) begin state <= 3'b111; count <= 32'b0; end end 3'b111: begin //Still counting so it can be demonstrated that factory image is still working count <= count + 1; reset <= 1'b0; param <= param; read_param <= 1'b0; data_in <= data_in; write_param <= 1'b0; reconfig <= 1'b0; //No way out of this state without an external event, this is the error condition end default: begin count <= count + 1; reset <= 1'b0; param <= param; read_param <= 1'b0; data_in <= data_in; write_param <= 1'b0; reconfig <= 1'b0; if (count==TIME_BETWEEN_STATES) begin state <= 3'b000; count <= 32'b0; end end endcase end //Cyclone V remote update remote_update remote_update_inst ( .clock(c10_clk50m),//clk40), .data_in(data_in), .param(param), .read_param(read_param), .reconfig(reconfig), .reset(reset), .reset_timer(reset_timer), .write_param(write_param), .busy(busy) ); endmodule
Application Image
odule c10rsu //application_image #(parameter TIME_TO_FACTORY = 32'h08777777) ( input wire c10_clk50m, //input clk, output [2:0] led ); // wire clk40; reg reconfig = 1'b0; reg [31:0] count_to_factory = 32'b0; //The count LED serves as a heartbeat, to see the design is functioning assign led[2] = count_to_factory[21]; assign led[1] = count_to_factory[21]; assign led[0] = count_to_factory[21]; //counter for lights and back to factory. always @(posedge c10_clk50m) //clk40) begin count_to_factory <= count_to_factory + 1; if (count_to_factory == TIME_TO_FACTORY) reconfig <= 1'b1; end //Instantiate the remote update block remote_update remote_update_inst ( .clock(c10_clk50m), //clk40), .data_in(32'b0), .param(3'b0), .read_param(0), .reconfig(reconfig), .reset(1'b0), .reset_timer(1'b0), .write_param(1'b0), .busy(), .data_out() ); endmodule
I believe I was able to solve the problem, the addressing I was using for my Serial interface was incorrect and setting my pointer to a much lower location than intended. When the sector erase was executed I believe it was over writing a portion of the data that was used to hold the Factory image.