|
@@ -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;
|
|
|
|