summaryrefslogtreecommitdiffstats
path: root/de1/fpga-flash-nor/de1flash.v
diff options
context:
space:
mode:
Diffstat (limited to 'de1/fpga-flash-nor/de1flash.v')
-rw-r--r--de1/fpga-flash-nor/de1flash.v893
1 files changed, 893 insertions, 0 deletions
diff --git a/de1/fpga-flash-nor/de1flash.v b/de1/fpga-flash-nor/de1flash.v
new file mode 100644
index 0000000..57cd5ec
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.v
@@ -0,0 +1,893 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2003-2011 H. Peter Anvin - All Rights Reserved
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall
+// be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// -----------------------------------------------------------------------
+
+//
+// de1flash.v
+//
+// Top-level module template for the Terasic DE1/Altera Cyclone II
+// Starter Board virtual JTAG programmer module
+//
+module de1flash (
+ input clock_50, // 50 MHz clock
+ input [1:0] clock_24, // 24 MHz clock (on two pins)
+ input [1:0] clock_27, // 27 MHz clock (on two pins)
+ input ext_clock, // External clock input
+
+ inout ps2_clk, // PS/2 keyboard clock
+ inout ps2_dat, // PS/2 keyboard data
+
+ output [9:0] ledr, // Red LEDs
+ output [7:0] ledg, // Green LEDs
+ output [6:0] s7_0, // 7-segment LEDs
+ output [6:0] s7_1, // 7-segment LEDs
+ output [6:0] s7_2, // 7-segment LEDs
+ output [6:0] s7_3, // 7-segment LEDs
+
+ input [3:0] key_n, // Pushbutton switches
+ input [9:0] sw, // Slide switches
+
+ output fl_rst_n, // Flash ROM RST#
+ output fl_ce_n, // Flash ROM CE#
+ output fl_oe_n, // Flash ROM OE#
+ output fl_we_n, // Flash ROM WE#
+ output [21:0] fl_a, // Flash ROM address bus
+ inout [7:0] fl_dq, // Flash ROM data bus
+
+ output [1:0] dram_ba, // SDRAM bank selects
+ output dram_ras_n, // SDRAM RAS#
+ output dram_cas_n, // SDRAM CAS#
+ output dram_cke, // SDRAM clock enable
+ output dram_clk, // SDRAM clock
+ output dram_cs_n, // SDRAM CS#
+ output dram_we_n, // SDRAM WE#
+ output [1:0] dram_dqm, // SDRAM DQM (per byte)
+ output [11:0] dram_a, // SDRAM address bus
+ inout [15:0] dram_dq, // SDRAM data bus
+
+ output sram_ce_n, // SRAM CE#
+ output sram_oe_n, // SRAM OE#
+ output sram_we_n, // SRAM WE#
+ output [1:0] sram_be_n, // SRAM UB#, LB#
+ output [17:0] sram_a, // SRAM address bus
+ inout [15:0] sram_dq, // SRAM data bus
+
+ output sd_clk, // SD card clock
+ inout sd_cmd, // SD card DI/MOSI/CMD
+ inout sd_dat0, // SD card SO/MISO/DAT0
+ inout sd_dat3, // SD card CS#/CD/DAT3
+
+ output uart_txd, // RS232 port TxD
+ input uart_rxd, // RS232 port RxD
+
+ output [3:0] vga_r, // VGA red
+ output [3:0] vga_g, // VGA green
+ output [3:0] vga_b, // VGA blue
+ output vga_hs, // VGA horz sync
+ output vga_vs, // VGA vert sync
+
+ output aud_xck, // Audio master clock
+ output aud_bclk, // Audio bitclock
+ output aud_dacdat, // Audio DAC data
+ output aud_daclrck, // Audio DAC framing
+ input aud_adcdat, // Audio ADC data
+ output aud_adclrck, // Audio ADC framing
+
+ inout i2c_scl, // I2C SCK line
+ inout i2c_sda, // I2C SDA line
+
+ inout [35:0] gpio_0, // GPIO headers
+ inout [35:0] gpio_1 // GPIO headers
+ );
+
+ wire fl_reset_n;
+
+ reg tdo;
+ wire [3:0] ir_in;
+ wire tck, tdi, v_sdr, v_cdr, v_uir, v_udr;
+
+ reg [71:0] jtag_wr_data;
+ reg [71:0] jtag_rd_data;
+ reg jtag_rd_valid;
+ reg [ 6:0] jtag_data_ctr;
+ wire [71:0] jtag_rd_q;
+ wire [ 7:0] jtag_wr_used;
+ reg [ 7:0] jtag_wr_free;
+ wire jtag_rd_empty;
+ reg jtag_bypass;
+ reg jtag_reset = 1'b0;
+
+ assign ledg[3:0] = ir_in;
+ assign ledg[7:4] = { v_udr, v_sdr, v_cdr, v_uir };
+
+ reg jtag_wr_wrq = 1'b0; // FIFO write strobe
+ reg jtag_rd_rrq = 1'b0; // FIFO read strobe
+
+ parameter cmd_read_fifo = 4'b0001;
+ parameter cmd_free_space = 4'b0010;
+ parameter cmd_write_fifo = 4'b0011;
+ parameter cmd_check_ready = 4'b0100;
+ parameter cmd_reset = 4'b0101;
+
+ // Shift registers and TDI input
+ always @(posedge tck)
+ begin
+ jtag_wr_wrq <= 1'b0;
+ jtag_rd_rrq <= 1'b0;
+ jtag_reset <= 1'b0;
+
+ if (v_udr)
+ begin
+ case (ir_in)
+ cmd_write_fifo:
+ jtag_wr_wrq <= 1'b1;
+ endcase // case(ir_in)
+ end // if (v_udr)
+ else if (v_cdr)
+ begin
+ case (ir_in)
+ cmd_read_fifo:
+ begin
+ jtag_rd_data <= { ~jtag_rd_empty, jtag_rd_q[70:0] };
+ jtag_rd_valid <= ~jtag_rd_empty;
+ jtag_data_ctr <= 7'd71;
+ end
+ cmd_free_space:
+ begin
+ jtag_wr_free <= ~jtag_wr_used;
+ end
+ endcase // case(ir_in)
+ end
+ else if (v_sdr)
+ begin
+ jtag_bypass <= tdi;
+
+ case (ir_in)
+ cmd_read_fifo:
+ begin
+ if ( jtag_data_ctr == 7'd2 )
+ begin
+ jtag_rd_rrq <= jtag_rd_valid;
+ jtag_rd_valid <= 1'b0;
+ end
+
+ if ( ~|jtag_data_ctr )
+ begin
+ jtag_rd_data <= { ~jtag_rd_empty, jtag_rd_q[70:0] };
+ jtag_rd_valid <= ~jtag_rd_empty;
+ jtag_data_ctr <= 7'd71;
+ end
+ else
+ begin
+ jtag_rd_data <= { tdi, jtag_rd_data[71:1] };
+ jtag_data_ctr <= jtag_data_ctr - 1'b1;
+ end
+ end // case: cmd_read_fifo
+ cmd_free_space:
+ jtag_wr_free <= { tdi, jtag_wr_free[ 7:1] };
+ cmd_write_fifo:
+ jtag_wr_data <= { tdi, jtag_wr_data[71:1] };
+ cmd_reset:
+ jtag_reset <= tdi;
+ endcase // case(ir_in)
+ end // if (v_sdr)
+ end
+
+ reg [2:0] jtag_ready = 3'b000;
+
+ always @(posedge tck)
+ jtag_ready <= { jtag_ready[1:0], fl_reset_n };
+
+ // TDO output MUX
+ always @ (*)
+ begin
+ case (ir_in)
+ cmd_read_fifo:
+ tdo <= jtag_rd_data[0];
+ cmd_free_space:
+ tdo <= jtag_wr_free[0];
+ cmd_write_fifo:
+ tdo <= jtag_wr_data[0];
+ cmd_reset:
+ tdo <= 1'b0; // Always read as zero
+ cmd_check_ready:
+ tdo <= jtag_ready[2];
+ default:
+ tdo <= jtag_bypass;
+ endcase // case(ir_in)
+ end // always @ (*)
+
+ vjtag_mega vjtag_mega_1
+ (
+ .ir_out ( ),
+ .tdo ( tdo ),
+ .ir_in ( ir_in ),
+ .tck ( tck ),
+ .tdi ( tdi ),
+ .virtual_state_cdr ( v_cdr ),
+ .virtual_state_cir ( ),
+ .virtual_state_e1dr ( v_udr ),
+ .virtual_state_e2dr ( ),
+ .virtual_state_pdr ( ),
+ .virtual_state_sdr ( v_sdr ),
+ .virtual_state_udr ( ),
+ .virtual_state_uir ( v_uir )
+ );
+
+ // ------------------------------------------------------------------
+ // Flash clock PLL and reset logic
+ // ------------------------------------------------------------------
+
+ wire pll_locked;
+ wire fl_clk;
+
+ pll pll (
+ .areset ( jtag_reset ),
+ .inclk0 ( clock_50 ),
+ .c0 ( fl_clk ), // 20 MHz
+ .locked ( pll_locked )
+ );
+
+ assign fl_reset_n = pll_locked;
+
+ // ------------------------------------------------------------------
+ // Write FIFO (JTAG -> programmer)
+ // ------------------------------------------------------------------
+
+ wire [71: 0] prog_wr_q;
+ wire prog_wr_rrq;
+ wire prog_wr_empty;
+
+ fl_fifo fl_wr_fifo
+ (
+ .aclr ( ~fl_reset_n ),
+
+ .wrclk ( tck ),
+ .data ( jtag_wr_data ),
+ .wrreq ( jtag_wr_wrq ),
+ .wrusedw ( jtag_wr_used ),
+ .wrfull ( ),
+
+ .rdclk ( fl_clk ),
+ .q ( prog_wr_q ),
+ .rdreq ( prog_wr_rrq ),
+ .rdempty ( prog_wr_empty )
+ );
+
+ // ------------------------------------------------------------------
+ // Read FIFO (programmer -> JTAG)
+ // ------------------------------------------------------------------
+
+ wire [71:0] prog_rd_data;
+ wire prog_rd_wrq;
+ wire prog_rd_full;
+
+ fl_fifo fl_rd_fifo
+ (
+ .aclr ( ~fl_reset_n ),
+
+ .wrclk ( fl_clk ),
+ .data ( prog_rd_data ),
+ .wrreq ( prog_rd_wrq ),
+ .wrusedw ( ),
+ .wrfull ( prog_rd_full ),
+
+ .rdclk ( tck ),
+ .q ( jtag_rd_q ),
+ .rdreq ( jtag_rd_rrq ),
+ .rdempty ( jtag_rd_empty )
+ );
+
+ // ------------------------------------------------------------------
+ // Flash state machine
+ // This is clocked at 20 MHz (50 ns); one clock cycle for each
+ // rising or falling edge
+ // ------------------------------------------------------------------
+
+ reg [63:0] fl_data; // Data shift register
+ reg [31:0] fl_bytectr; // Byte counter
+ reg [ 2:0] fl_rbctr; // Read bytes in shift register
+ reg [ 3:0] fl_rbcmd; // Command code
+ reg [31:0] fl_addr;
+
+ reg fl_ce_q;
+ reg fl_oe_q;
+ reg fl_we_q;
+ reg [31:0] fl_a_q;
+ reg [ 7:0] fl_d_q;
+ reg fl_d_en;
+
+ assign fl_rst_n = fl_reset_n;
+ assign fl_ce_n = ~fl_ce_q;
+ assign fl_oe_n = ~fl_oe_q;
+ assign fl_we_n = ~fl_we_q;
+ assign fl_a = fl_a_q[21:0];
+ assign fl_dq = fl_d_en ? fl_d_q : 8'hzz;
+
+ reg [4:0] prog_state;
+ parameter pst_idle = 5'h00;
+ parameter pst_delay = 5'h01;
+ parameter pst_status = 5'h02;
+ parameter pst_read0 = 5'h04;
+ parameter pst_read1 = 5'h05;
+ parameter pst_read2 = 5'h06;
+ parameter pst_readpad = 5'h07;
+ parameter pst_write0 = 5'h08;
+ parameter pst_write1 = 5'h09;
+ parameter pst_zchk0 = 5'h0A;
+ parameter pst_zchk1 = 5'h0B;
+ parameter pst_zchk2 = 5'h0C;
+ parameter pst_crc0 = 5'h0D;
+ parameter pst_crc1 = 5'h0E;
+ parameter pst_crc2 = 5'h0F;
+ parameter pst_program0 = 5'h10;
+ parameter pst_program1 = 5'h11;
+ parameter pst_program2 = 5'h12;
+ parameter pst_program3 = 5'h13;
+ parameter pst_program4 = 5'h14;
+ parameter pst_program5 = 5'h15;
+ parameter pst_program6 = 5'h16;
+ parameter pst_program7 = 5'h17;
+ parameter pst_program8 = 5'h18;
+ parameter pst_program9 = 5'h19;
+ parameter pst_program10 = 5'h1A;
+ parameter pst_program11 = 5'h1B;
+ parameter pst_program12 = 5'h1C;
+ parameter pst_program13 = 5'h1D;
+ parameter pst_program14 = 5'h1E;
+
+ reg rd_ack;
+
+ reg [7:0] pgm_data;
+ reg [7:0] tst_data;
+
+ // Debugging... registering these is "free" since there are
+ // registers in the I/O buffers, and deconstrains the design
+ reg [9:0] ledr_q;
+ assign ledr = ledr_q;
+
+ always @(posedge fl_clk or negedge fl_reset_n)
+ if (~fl_reset_n)
+ begin
+ ledr_q <= ~10'b0;
+ end
+ else
+ begin
+ ledr_q[0] <= prog_rd_full;
+ ledr_q[1] <= fl_ce_q;
+ ledr_q[2] <= fl_oe_q;
+ ledr_q[3] <= fl_we_q;
+ ledr_q[4] <= fl_d_en;
+ ledr_q[9:5] <= prog_state;
+ end
+
+ reg [6:0] s7_0_q;
+ reg [6:0] s7_1_q;
+ reg [6:0] s7_2_q;
+ reg [6:0] s7_3_q;
+
+ wire [6:0] s7_0_w;
+ wire [6:0] s7_1_w;
+ wire [6:0] s7_2_w;
+ wire [6:0] s7_3_w;
+
+ assign s7_0 = s7_0_q;
+ assign s7_1 = s7_1_q;
+ assign s7_2 = s7_2_q;
+ assign s7_3 = s7_3_q;
+
+ hexled hexled0 ( .value (fl_addr[11: 8]), .s7 (s7_0_w) );
+ hexled hexled1 ( .value (fl_addr[15:12]), .s7 (s7_1_w) );
+ hexled hexled2 ( .value (fl_addr[19:16]), .s7 (s7_2_w) );
+ hexled hexled3 ( .value (fl_addr[23:20]), .s7 (s7_3_w) );
+
+ reg [2:0] rd_cnt;
+
+ always @(posedge fl_clk or negedge fl_reset_n)
+ if (~fl_reset_n)
+ begin
+ s7_0_q <= ~7'b1000000;
+ s7_1_q <= ~7'b1000000;
+ s7_2_q <= ~7'b1000000;
+ s7_3_q <= ~7'b1000000;
+ end
+ else
+ begin
+ s7_0_q <= s7_0_w;
+ s7_1_q <= s7_1_w;
+ s7_2_q <= s7_2_w;
+ s7_3_q <= s7_3_w;
+ end
+
+ assign prog_wr_rrq = ~prog_wr_empty & (prog_state == pst_idle);
+ assign prog_rd_wrq = rd_ack;
+ assign prog_rd_data = { 1'b1, rd_cnt, fl_rbcmd, fl_data };
+
+ always @(negedge fl_reset_n or posedge fl_clk)
+ if (~fl_reset_n)
+ rd_cnt <= 3'b000;
+ else
+ rd_cnt <= rd_cnt + rd_ack;
+
+ wire bump_addr =
+ (prog_state == pst_read2) |
+ (prog_state == pst_zchk2) |
+ (prog_state == pst_crc2) |
+ (prog_state == pst_write1) |
+ ((prog_state == pst_program3) & ~|(tst_data & ~fl_data[7:0])) |
+ ((prog_state == pst_program14) & (tst_data == pgm_data));
+
+ wire [31:0] tst_crc;
+ crc_32_d8 crcgen
+ (
+ .data ( tst_data ),
+ .in ( fl_data[31:0] ),
+ .out ( tst_crc )
+ );
+ reg bump_crc;
+
+ always @(negedge fl_reset_n or posedge fl_clk)
+ if (~fl_reset_n)
+ begin
+ fl_ce_q <= 1'b0;
+ fl_oe_q <= 1'b0;
+ fl_we_q <= 1'b0;
+ fl_addr <= 32'h0;
+ fl_a_q <= 32'h0;
+ fl_d_q <= 8'h0;
+ fl_d_en <= 1'b0;
+
+ fl_data <= 64'bx;
+ fl_bytectr <= 32'h0;
+ fl_rbctr <= 3'h0;
+ fl_rbcmd <= 4'bx;
+
+ prog_state <= pst_idle;
+ rd_ack <= 1'b0;
+ bump_crc <= 1'b0;
+
+ pgm_data <= 8'hxx;
+ tst_data <= 8'hff;
+ end
+ else
+ begin
+ fl_ce_q <= 1'b0;
+ fl_oe_q <= 1'b0;
+ fl_we_q <= 1'b0;
+ fl_d_en <= 1'b0;
+
+ rd_ack <= 1'b0;
+ bump_crc <= 1'b0;
+
+ fl_addr <= fl_addr + bump_addr;
+
+ case ( prog_state )
+ pst_idle:
+ begin
+ fl_rbctr <= 3'h0;
+ fl_rbcmd <= prog_wr_q[71:68];
+ tst_data <= 8'hff;
+
+ if ( ~prog_wr_empty )
+ casez ( prog_wr_q[71:68] )
+ 4'b0010: // Delay command
+ begin
+ fl_bytectr <= prog_wr_q[31:0];
+ prog_state <= pst_delay;
+ end
+ 4'b0101: // Zero check
+ begin
+ fl_addr <= prog_wr_q[63:32];
+ fl_bytectr <= prog_wr_q[31:0];
+ prog_state <= pst_zchk0;
+ end
+ 4'b0110: // Read back address, token
+ begin
+ fl_data <= { fl_addr, prog_wr_q[31:0] };
+ prog_state <= pst_status;
+ end
+ 4'b0111: // CRC32
+ begin
+ fl_addr <= prog_wr_q[63:32];
+ fl_bytectr <= prog_wr_q[31:0];
+ fl_data[63:32] <= 32'hxxxxxxxx;
+ fl_data[31: 0] <= 32'h00000000;
+ prog_state <= pst_crc0;
+ end
+ 4'b100z: // Write bytes command
+ begin
+ fl_data <= prog_wr_q[63:0];
+ if ( prog_wr_q[68] )
+ fl_addr <= prog_wr_q[63:32];
+ prog_state <= pst_write0;
+ end
+ 4'b1011: // Program bytes command
+ begin
+ fl_bytectr <= { 28'b0, prog_wr_q[67:64] };
+ fl_data <= prog_wr_q[63:0];
+ prog_state <= pst_program0;
+ end
+ 4'b1101: // Set address register/read command
+ begin
+ fl_addr <= prog_wr_q[63:32];
+ fl_bytectr <= prog_wr_q[31:0];
+ prog_state <= pst_read0;
+ end
+ endcase // case( prog_wr_q[71:69] )
+ end // case: pst_idle
+
+ pst_delay:
+ begin
+ if ( |fl_bytectr )
+ fl_bytectr <= fl_bytectr - 1'b1;
+ else
+ prog_state <= pst_idle;
+ end
+
+ pst_status:
+ begin
+ if ( ~prog_rd_full )
+ begin
+ rd_ack <= 1'b1;
+ prog_state <= pst_idle;
+ end
+ end
+
+ pst_read0: // Read initial state
+ begin
+ fl_a_q <= fl_addr;
+ if ( |fl_bytectr )
+ begin
+ if ( ~prog_rd_full )
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_read1;
+ end
+ end
+ else if ( |fl_rbctr )
+ begin
+ if ( ~prog_rd_full )
+ prog_state <= pst_readpad;
+ end
+ else
+ prog_state <= pst_idle;
+ end // case: pst_read0
+
+ pst_read1: // Read output waveform #1
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_read2;
+ end
+
+ pst_read2:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_data <= { fl_dq, fl_data[63:8] };
+ rd_ack <= &fl_rbctr;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ fl_rbctr <= fl_rbctr + 1'b1;
+ prog_state <= pst_read0;
+ end
+
+ pst_readpad:
+ begin
+ fl_data <= { 8'hFF, fl_data[63:8] };
+ rd_ack <= &fl_rbctr;
+ fl_rbctr <= fl_rbctr + 1'b1;
+ prog_state <= pst_read0;
+ end
+
+ pst_zchk0: // Zero check
+ begin
+ fl_a_q <= fl_addr;
+ if ( (&tst_data) & (|fl_bytectr) )
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ fl_data[63:32] <= 32'hxxxxxxxx;
+ fl_data[31: 0] <= 32'hxxxxxxxx;
+ prog_state <= pst_zchk1;
+ end
+ else if ( ~prog_rd_full )
+ begin
+ fl_data[63:32] <= fl_addr;
+ fl_data[31: 8] <= 24'hffffff;
+ fl_data[ 7: 0] <= tst_data;
+ rd_ack <= 1'b1;
+ prog_state <= pst_idle;
+ end // else: !if( |fl_bytectr )
+ end // case: pst_zchk0
+
+ pst_zchk1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_zchk2;
+ end
+
+ pst_zchk2:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ prog_state <= pst_zchk0;
+ end
+
+ pst_crc0: // CRC32
+ begin
+ fl_a_q <= fl_addr;
+ if ( bump_crc )
+ fl_data[31: 0] <= tst_crc;
+ if ( |fl_bytectr )
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ fl_data[63:32] <= 32'hxxxxxxxx;
+ prog_state <= pst_crc1;
+ end
+ else if ( ~prog_rd_full )
+ begin
+ fl_data[63:32] <= fl_addr;
+ rd_ack <= 1'b1;
+ prog_state <= pst_idle;
+ end // else: !if( |fl_bytectr )
+ end // case: pst_crc0
+
+ pst_crc1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_crc2;
+ end
+
+ pst_crc2:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ bump_crc <= 1'b1;
+ prog_state <= pst_crc0;
+ end
+
+ pst_write0:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= fl_data[7:0];
+ fl_a_q <= fl_data[63:32];
+ prog_state <= pst_write1;
+ end
+
+ pst_write1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_idle;
+ end
+
+ // Programming algorithm: read individual bytes to avoid
+ // hanging the flash chip due to zero bits
+ pst_program0:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ fl_a_q <= fl_addr;
+ prog_state <= pst_program1;
+ end
+
+ pst_program1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_program2;
+ end
+
+ pst_program2:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ prog_state <= pst_program3;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ end
+
+ pst_program3:
+ begin
+ fl_ce_q <= 1'b1;
+ pgm_data <= tst_data & fl_data[7:0];
+ fl_data <= { 8'hFF, fl_data[63:8] };
+
+ if ( |(tst_data & ~fl_data[7:0]) )
+ begin
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= 8'hAA;
+ fl_a_q <= 32'hAAAA_AAAA;
+ prog_state <= pst_program4;
+ end
+ else
+ begin
+ if ( |fl_bytectr )
+ prog_state <= pst_program0;
+ else
+ prog_state <= pst_idle;
+ end
+ end // case: pst_program3
+
+ pst_program4:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program5;
+ end
+
+ pst_program5:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= 8'h55;
+ fl_a_q <= 32'h5555_5555;
+ prog_state <= pst_program6;
+ end
+
+ pst_program6:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program7;
+ end
+
+ pst_program7:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= 8'hA0;
+ fl_a_q <= 32'hAAAA_AAAA;
+ prog_state <= pst_program8;
+ end
+
+ pst_program8:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program9;
+ end
+
+ pst_program9:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= pgm_data;
+ fl_a_q <= fl_addr;
+ prog_state <= pst_program10;
+ end
+
+ pst_program10:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program11;
+ end
+
+ pst_program11:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_program12;
+ end
+
+ pst_program12:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_program13;
+ end
+
+ pst_program13:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ prog_state <= pst_program14;
+ end
+
+ pst_program14:
+ begin
+ fl_ce_q <= 1'b1;
+ if ( tst_data != pgm_data )
+ prog_state <= pst_program11;
+ else if ( |fl_bytectr )
+ prog_state <= pst_program0;
+ else
+ prog_state <= pst_idle;
+ end
+ endcase // case( prog_state )
+ end
+
+ // ------------------------------------------------------------------
+ // Unused hardware ports
+ // ------------------------------------------------------------------
+
+ // PS/2 port
+ assign ps2_clk = 1'bz;
+ assign ps2_dat = 1'bz;
+
+ // SDRAM
+ assign dram_ba = 2'b11;
+ assign dram_ras_n = 1'b1;
+ assign dram_cas_n = 1'b1;
+ assign dram_cke = 1'b1;
+ assign dram_clk = 1'b1;
+ assign dram_cs_n = 1'b1;
+ assign dram_we_n = 1'b1;
+ assign dram_dqm = 2'b11;
+ assign dram_a = ~12'b0;
+ assign dram_dq = 16'hzzzz;
+
+ // SRAM
+ assign sram_ce_n = 1'b1;
+ assign sram_oe_n = 1'b1;
+ assign sram_we_n = 1'b1;
+ assign sram_be_n = 2'b11;
+ assign sram_a = ~18'b0;
+ assign sram_dq = 16'hzzzz;
+
+ // SD card
+ assign sd_clk = 1'b1;
+ assign sd_cmd = 1'bz;
+ assign sd_dat0 = 1'bz;
+ assign sd_dat3 = 1'bz;
+
+ // RS232
+ assign uart_txd = 1'b1;
+
+ // Video
+ assign vga_r = 4'b0;
+ assign vga_g = 4'b0;
+ assign vga_b = 4'b0;
+ assign vga_hs = 1'b0;
+ assign vga_vs = 1'b0;
+
+ // Audio I2S
+ assign aud_xck = 1'b1;
+ assign aud_bclk = 1'b1;
+ assign aud_dacdat = 1'b1;
+ assign aud_daclrck = 1'b1;
+ assign aud_adclrck = 1'b1;
+
+ // Audio I2C
+ assign i2c_scl = 1'bz;
+ assign i2c_sda = 1'bz;
+
+ // GPIO
+ assign gpio_0 = 36'hz_zzzz_zzzz;
+ assign gpio_1 = 36'hz_zzzz_zzzz;
+
+endmodule // de1flash