|  | @@ -72,7 +72,7 @@ module max80 (
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	      // USB serial (naming is FPGA as DCE)
 | 
	
		
			
				|  |  |  	      input	    tty_txd,
 | 
	
		
			
				|  |  | -	      output	    tty_rxd,
 | 
	
		
			
				|  |  | +	      inout	    tty_rxd,
 | 
	
		
			
				|  |  |  	      input	    tty_rts,
 | 
	
		
			
				|  |  |  	      output	    tty_cts,
 | 
	
		
			
				|  |  |  	      input	    tty_dtr,
 | 
	
	
		
			
				|  | @@ -120,9 +120,6 @@ module max80 (
 | 
	
		
			
				|  |  |     //   PLLs and reset
 | 
	
		
			
				|  |  |     // -----------------------------------------------------------------------
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   // Assert internal reset for 4096 cycles after PLL lock
 | 
	
		
			
				|  |  | -   parameter reset_pow2 = 12;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |     reg			    rst_n      = 1'b0;	// Internal system reset
 | 
	
		
			
				|  |  |     reg			    hard_rst_n = 1'b0;	// Strict POR reset only
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -143,9 +140,10 @@ module max80 (
 | 
	
		
			
				|  |  |     //  sdram_clk, sys_clk    - 2:1 ratio
 | 
	
		
			
				|  |  |     //  vid_hdmiclk, vid_clk  - 5:1 ratio
 | 
	
		
			
				|  |  |     //
 | 
	
		
			
				|  |  | +   wire     reset_plls;
 | 
	
		
			
				|  |  |     wire     master_clk;		// 336 MHz internal master clock
 | 
	
		
			
				|  |  |     pll2 pll2 (
 | 
	
		
			
				|  |  | -	      .areset ( 1'b0 ),
 | 
	
		
			
				|  |  | +	      .areset ( reset_plls ),
 | 
	
		
			
				|  |  |  	      .locked ( pll_locked[2] ),
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	      .inclk0 ( clock_48 ),
 | 
	
	
		
			
				|  | @@ -181,32 +179,47 @@ module max80 (
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     wire all_plls_locked = &pll_locked;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   // sys_clk pulse generation of various powers of two
 | 
	
		
			
				|  |  | -   // Also used to generate rst_n
 | 
	
		
			
				|  |  | -   reg [23:1] sys_clk_ctr;
 | 
	
		
			
				|  |  | -   reg [23:1] sys_clk_ctr_q;
 | 
	
		
			
				|  |  | -   reg [23:1] sys_clk_stb;
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // sys_clk pulse generation of various powers of two; allows us to
 | 
	
		
			
				|  |  | +   // reuse the same counter for a lot of things that require periodic
 | 
	
		
			
				|  |  | +   // timing events without strong requirements on the specific timing.
 | 
	
		
			
				|  |  | +   // The first strobe is asserted 2^n cycles after rst_n goes high.
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // The same counter is used to hold rst_n and hard_rst_n low for
 | 
	
		
			
				|  |  | +   // 2^reset_pow2 cycles.
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // XXX: reuse this counter for the CPU cycle counter.
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   parameter reset_pow2 = 12;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   reg [1:0]  reset_cmd_q;
 | 
	
		
			
				|  |  | -   wire       reset_cmd;
 | 
	
		
			
				|  |  | +   reg [31:0] sys_clk_ctr;
 | 
	
		
			
				|  |  | +   reg [31:0] sys_clk_ctr_q;
 | 
	
		
			
				|  |  | +   reg [31:1] sys_clk_stb;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   // 3 types of reset: system, hard, and reconfig
 | 
	
		
			
				|  |  | +   reg  [3:1] reset_cmd_q;
 | 
	
		
			
				|  |  | +   wire [3:1] reset_cmd;
 | 
	
		
			
				|  |  | +   reg	      soft_reset_q;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     always @(negedge all_plls_locked or posedge sys_clk)
 | 
	
		
			
				|  |  |       if (~all_plls_locked)
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  hard_rst_n    <= 1'b0;
 | 
	
		
			
				|  |  | -	  rst_n         <= 1'b0;
 | 
	
		
			
				|  |  | -	  reset_cmd_q   <= 2'b0;
 | 
	
		
			
				|  |  | -	  sys_clk_ctr   <= 1'b0;
 | 
	
		
			
				|  |  | -	  sys_clk_ctr_q <= 1'b0;
 | 
	
		
			
				|  |  | -	  sys_clk_stb   <= 1'b0;
 | 
	
		
			
				|  |  | +	  hard_rst_n     <= 1'b0;
 | 
	
		
			
				|  |  | +	  rst_n          <= 1'b0;
 | 
	
		
			
				|  |  | +	  reset_cmd_q    <= 3'b0;
 | 
	
		
			
				|  |  | +	  soft_reset_q   <= 1'b0;
 | 
	
		
			
				|  |  | +	  sys_clk_ctr    <= (-'sb1) << reset_pow2;
 | 
	
		
			
				|  |  | +	  sys_clk_ctr_q  <= 'b0;
 | 
	
		
			
				|  |  | +	  sys_clk_stb    <= 'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  reset_cmd_q <= { reset_cmd_q[0], reset_cmd };
 | 
	
		
			
				|  |  | +	  reset_cmd_q    <= reset_cmd;
 | 
	
		
			
				|  |  | +	  soft_reset_q   <= reset_cmd_q[1]; // Edge detect for soft reset
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	  if (reset_cmd_q == 2'b01)
 | 
	
		
			
				|  |  | +	  if (reset_cmd_q[1] & ~soft_reset_q)
 | 
	
		
			
				|  |  |  	    begin
 | 
	
		
			
				|  |  | -	       sys_clk_ctr   <= 1'b0;
 | 
	
		
			
				|  |  | +	       sys_clk_ctr   <= (-'sb1) << reset_pow2;
 | 
	
		
			
				|  |  |  	       sys_clk_ctr_q <= 1'b0;
 | 
	
		
			
				|  |  |  	       sys_clk_stb   <= 1'b0;
 | 
	
		
			
				|  |  |  	       rst_n         <= 1'b0;
 | 
	
	
		
			
				|  | @@ -214,10 +227,10 @@ module max80 (
 | 
	
		
			
				|  |  |  	  else
 | 
	
		
			
				|  |  |  	    begin
 | 
	
		
			
				|  |  |  	       sys_clk_ctr   <= sys_clk_ctr + 1'b1;
 | 
	
		
			
				|  |  | -	       sys_clk_ctr_q <= sys_clk_ctr;
 | 
	
		
			
				|  |  | +	       sys_clk_ctr_q <= ~rst_n ? 'b0 : sys_clk_ctr;
 | 
	
		
			
				|  |  |  	       sys_clk_stb   <= ~sys_clk_ctr & sys_clk_ctr_q;
 | 
	
		
			
				|  |  | -	       rst_n         <= rst_n      | sys_clk_stb[reset_pow2];
 | 
	
		
			
				|  |  | -	       hard_rst_n    <= hard_rst_n | sys_clk_stb[reset_pow2];
 | 
	
		
			
				|  |  | +	       rst_n         <= rst_n      | ~sys_clk_ctr[reset_pow2];
 | 
	
		
			
				|  |  | +	       hard_rst_n    <= hard_rst_n | ~sys_clk_ctr[reset_pow2];
 | 
	
		
			
				|  |  |  	    end
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -324,7 +337,9 @@ module max80 (
 | 
	
		
			
				|  |  |     sdram #(.port1_count(dram_port_count))
 | 
	
		
			
				|  |  |     sdram (
 | 
	
		
			
				|  |  |  	  .rst_n    ( rst_n ),
 | 
	
		
			
				|  |  | -	  .clk      ( sdram_clk ), // Internal clock
 | 
	
		
			
				|  |  | +	  .clk      ( sdram_clk ),       // Internal memory clock
 | 
	
		
			
				|  |  | +	  .init_tmr ( sys_clk_stb[14] ), // > 100 μs (tP) after reset
 | 
	
		
			
				|  |  | +	  .rfsh_tmr ( sys_clk_stb[8] ),  // < 3.9 μs (tREFI/2)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  .sr_cke   ( sr_cke ),
 | 
	
		
			
				|  |  |  	  .sr_cs_n  ( sr_cs_n ),
 | 
	
	
		
			
				|  | @@ -581,15 +596,32 @@ module max80 (
 | 
	
		
			
				|  |  |  	  usb_rxd_break_rst <= usb_rxd_break & ~usb_rxd_break_q;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   assign reset_cmd =
 | 
	
		
			
				|  |  | -		     // Explicit reset command
 | 
	
		
			
				|  |  | -		     (sysreg[3] & cpu_mem_wstrb[0] & cpu_mem_wdata[0]) |
 | 
	
		
			
				|  |  | -		     // CPU hung
 | 
	
		
			
				|  |  | -		     cpu_trap |
 | 
	
		
			
				|  |  | -		     // BREAK received on USB tty
 | 
	
		
			
				|  |  | -		     usb_rxd_break_rst;
 | 
	
		
			
				|  |  | +   // Reset control. Note that CPU reset command 0 is intentionally ignored.
 | 
	
		
			
				|  |  | +   wire [3:0] cpu_reset_cmd =
 | 
	
		
			
				|  |  | +	      (sysreg[3] & cpu_mem_wstrb[0]) << cpu_mem_wdata[1:0];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // Soft system reset: FPGA not reloaded, PLLs not reset,
 | 
	
		
			
				|  |  | +   // USB and console are not reset
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // Triggered by:
 | 
	
		
			
				|  |  | +   //  - CPU reset command 1
 | 
	
		
			
				|  |  | +   //  - CPU entering TRAP state (irrecoverable error)
 | 
	
		
			
				|  |  | +   //  - BREAK received on USB console
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   assign reset_cmd[1] = cpu_reset_cmd[1] | cpu_trap | usb_rxd_break_rst;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // Hard system reset: FPGA not reloaded, PLLs reset, all hw units reset
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   assign reset_cmd[2] = cpu_reset_cmd[2];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   // FPGA reload reset
 | 
	
		
			
				|  |  | +   //
 | 
	
		
			
				|  |  | +   assign reset_cmd[3] = cpu_reset_cmd[3];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // LED indication from the CPU
 | 
	
		
			
				|  |  | +   // LED indication from the CPU
 | 
	
		
			
				|  |  |     reg [2:0]   led_q;
 | 
	
		
			
				|  |  |     always @(negedge rst_n or posedge sys_clk)
 | 
	
		
			
				|  |  |       if (~rst_n)
 | 
	
	
		
			
				|  | @@ -605,10 +637,14 @@ module max80 (
 | 
	
		
			
				|  |  |     wire        rtc_clk_s;
 | 
	
		
			
				|  |  |     rng #(.nclocks(2), .width(32)) rng
 | 
	
		
			
				|  |  |       (
 | 
	
		
			
				|  |  | -      .sys_clk ( sys_clk ),
 | 
	
		
			
				|  |  | -      .q       ( sysreg_rdata[4] ),
 | 
	
		
			
				|  |  | -      .clocks  ( { rtc_clk_s, abc_clk_s } ),
 | 
	
		
			
				|  |  | -      .rngio   ( rngio )
 | 
	
		
			
				|  |  | +      .rst_n     ( rst_n ),
 | 
	
		
			
				|  |  | +      .sys_clk   ( sys_clk ),
 | 
	
		
			
				|  |  | +      .read_stb  ( iodev_valid_random ),
 | 
	
		
			
				|  |  | +      .latch_stb ( sys_clk_stb[16] ),
 | 
	
		
			
				|  |  | +      .ready     ( iodev_irq_random ),
 | 
	
		
			
				|  |  | +      .q         ( iodev_rdata_random ),
 | 
	
		
			
				|  |  | +      .clocks    ( { rtc_clk_s, abc_clk_s } ),
 | 
	
		
			
				|  |  | +      .rngio     ( rngio )
 | 
	
		
			
				|  |  |        );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     //
 | 
	
	
		
			
				|  | @@ -685,7 +721,7 @@ module max80 (
 | 
	
		
			
				|  |  |  		  );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     assign tty_data_in      = tty_txd;
 | 
	
		
			
				|  |  | -   assign tty_rxd          = tty_data_out;
 | 
	
		
			
				|  |  | +   assign tty_rxd          = tty_dtr ? 1'bz : tty_data_out;
 | 
	
		
			
				|  |  |     assign tty_rts_in       = tty_rts;
 | 
	
		
			
				|  |  |     assign tty_cts          = tty_cts_out;
 | 
	
		
			
				|  |  |  
 |