diff options
Diffstat (limited to 'de1/fpga-flash-nor/de1flash.v')
| -rw-r--r-- | de1/fpga-flash-nor/de1flash.v | 893 | 
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 | 
