Browse Source

Minimal console serial port (1000000-N81) "Hello, World!"

H. Peter Anvin 3 years ago
parent
commit
4410a635c4

+ 193 - 0
fpga/ip/fifo.v

@@ -0,0 +1,193 @@
+// megafunction wizard: %FIFO%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: dcfifo 
+
+// ============================================================
+// File Name: fifo.v
+// Megafunction Name(s):
+// 			dcfifo
+//
+// Simulation Library Files(s):
+// 			altera_mf
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 20.1.1 Build 720 11/11/2020 SJ Lite Edition
+// ************************************************************
+
+
+//Copyright (C) 2020  Intel Corporation. All rights reserved.
+//Your use of Intel Corporation's design tools, logic functions 
+//and other software and tools, and any partner logic 
+//functions, and any output files from any of the foregoing 
+//(including device programming or simulation files), and any 
+//associated documentation or information are expressly subject 
+//to the terms and conditions of the Intel Program License 
+//Subscription Agreement, the Intel Quartus Prime License Agreement,
+//the Intel FPGA IP License Agreement, or other applicable license
+//agreement, including, without limitation, that your use is for
+//the sole purpose of programming logic devices manufactured by
+//Intel and sold by Intel or its authorized distributors.  Please
+//refer to the applicable agreement for further details, at
+//https://fpgasoftware.intel.com/eula.
+
+
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+module fifo (
+	aclr,
+	data,
+	rdclk,
+	rdreq,
+	wrclk,
+	wrreq,
+	q,
+	rdempty,
+	rdusedw,
+	wrfull,
+	wrusedw);
+
+	input	  aclr;
+	input	[7:0]  data;
+	input	  rdclk;
+	input	  rdreq;
+	input	  wrclk;
+	input	  wrreq;
+	output	[7:0]  q;
+	output	  rdempty;
+	output	[8:0]  rdusedw;
+	output	  wrfull;
+	output	[8:0]  wrusedw;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_off
+`endif
+	tri0	  aclr;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_on
+`endif
+
+	wire [7:0] sub_wire0;
+	wire  sub_wire1;
+	wire [8:0] sub_wire2;
+	wire  sub_wire3;
+	wire [8:0] sub_wire4;
+	wire [7:0] q = sub_wire0[7:0];
+	wire  rdempty = sub_wire1;
+	wire [8:0] rdusedw = sub_wire2[8:0];
+	wire  wrfull = sub_wire3;
+	wire [8:0] wrusedw = sub_wire4[8:0];
+
+	dcfifo	dcfifo_component (
+				.aclr (aclr),
+				.data (data),
+				.rdclk (rdclk),
+				.rdreq (rdreq),
+				.wrclk (wrclk),
+				.wrreq (wrreq),
+				.q (sub_wire0),
+				.rdempty (sub_wire1),
+				.rdusedw (sub_wire2),
+				.wrfull (sub_wire3),
+				.wrusedw (sub_wire4),
+				.eccstatus (),
+				.rdfull (),
+				.wrempty ());
+	defparam
+		dcfifo_component.intended_device_family = "Cyclone IV E",
+		dcfifo_component.lpm_numwords = 512,
+		dcfifo_component.lpm_showahead = "ON",
+		dcfifo_component.lpm_type = "dcfifo",
+		dcfifo_component.lpm_width = 8,
+		dcfifo_component.lpm_widthu = 9,
+		dcfifo_component.overflow_checking = "ON",
+		dcfifo_component.rdsync_delaypipe = 4,
+		dcfifo_component.read_aclr_synch = "OFF",
+		dcfifo_component.underflow_checking = "ON",
+		dcfifo_component.use_eab = "ON",
+		dcfifo_component.write_aclr_synch = "OFF",
+		dcfifo_component.wrsync_delaypipe = 4;
+
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
+// Retrieval info: PRIVATE: Clock NUMERIC "4"
+// Retrieval info: PRIVATE: Depth NUMERIC "512"
+// Retrieval info: PRIVATE: Empty NUMERIC "1"
+// Retrieval info: PRIVATE: Full NUMERIC "1"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: Optimize NUMERIC "0"
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
+// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "8"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
+// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
+// Retrieval info: PRIVATE: output_width NUMERIC "8"
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "1"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "512"
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "8"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "9"
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "4"
+// Retrieval info: CONSTANT: READ_ACLR_SYNCH STRING "OFF"
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"
+// Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "OFF"
+// Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "4"
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND "aclr"
+// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
+// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
+// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL "rdclk"
+// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL "rdempty"
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
+// Retrieval info: USED_PORT: rdusedw 0 0 9 0 OUTPUT NODEFVAL "rdusedw[8..0]"
+// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL "wrclk"
+// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL "wrfull"
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
+// Retrieval info: USED_PORT: wrusedw 0 0 9 0 OUTPUT NODEFVAL "wrusedw[8..0]"
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
+// Retrieval info: CONNECT: @data 0 0 8 0 data 0 0 8 0
+// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
+// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
+// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
+// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0
+// Retrieval info: CONNECT: rdusedw 0 0 9 0 @rdusedw 0 0 9 0
+// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0
+// Retrieval info: CONNECT: wrusedw 0 0 9 0 @wrusedw 0 0 9 0
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.inc FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.cmp FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo.bsf FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_bb.v TRUE
+// Retrieval info: LIB_FILE: altera_mf

+ 10 - 8
fpga/max80.qsf

@@ -150,6 +150,15 @@ set_global_assignment -name QII_AUTO_PACKED_REGISTERS "SPARSE AUTO"
 set_global_assignment -name SAVE_DISK_SPACE OFF
 set_global_assignment -name TIMING_ANALYZER_MULTICORNER_ANALYSIS ON
 set_global_assignment -name SMART_RECOMPILE ON
+set_global_assignment -name EDA_TEST_BENCH_ENABLE_STATUS TEST_BENCH_MODE -section_id eda_simulation
+set_global_assignment -name EDA_NATIVELINK_SIMULATION_TEST_BENCH testclk -section_id eda_simulation
+set_global_assignment -name EDA_TEST_BENCH_NAME testclk -section_id eda_simulation
+set_global_assignment -name EDA_DESIGN_INSTANCE_NAME max80 -section_id testclk
+set_global_assignment -name EDA_TEST_BENCH_RUN_SIM_FOR "1 ms" -section_id testclk
+set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME testclk -section_id testclk
+set_global_assignment -name EDA_TEST_BENCH_FILE simulation/testclk.sv -section_id testclk
+set_global_assignment -name EDA_NATIVELINK_PORTABLE_FILE_PATHS ON -section_id eda_simulation
+set_global_assignment -name SYSTEMVERILOG_FILE tty.sv
 set_global_assignment -name VERILOG_FILE ip/fastmem_ip.v
 set_global_assignment -name SYSTEMVERILOG_FILE fast_mem.sv
 set_global_assignment -name MIF_FILE ../fw/boot.mif
@@ -170,12 +179,5 @@ set_global_assignment -name SDC_FILE max80.sdc
 set_global_assignment -name SYSTEMVERILOG_FILE max80.sv
 set_global_assignment -name SOURCE_FILE max80.pins
 set_global_assignment -name SOURCE_TCL_SCRIPT_FILE scripts/pins.tcl
-set_global_assignment -name EDA_TEST_BENCH_ENABLE_STATUS TEST_BENCH_MODE -section_id eda_simulation
-set_global_assignment -name EDA_NATIVELINK_SIMULATION_TEST_BENCH testclk -section_id eda_simulation
-set_global_assignment -name EDA_TEST_BENCH_NAME testclk -section_id eda_simulation
-set_global_assignment -name EDA_DESIGN_INSTANCE_NAME max80 -section_id testclk
-set_global_assignment -name EDA_TEST_BENCH_RUN_SIM_FOR "1 ms" -section_id testclk
-set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME testclk -section_id testclk
-set_global_assignment -name EDA_TEST_BENCH_FILE simulation/testclk.sv -section_id testclk
-set_global_assignment -name EDA_NATIVELINK_PORTABLE_FILE_PATHS ON -section_id eda_simulation
+set_global_assignment -name QIP_FILE ip/fifo.qip
 set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

+ 12 - 4
fpga/max80.sv

@@ -404,10 +404,6 @@ module max80 (
    assign sd_cmd    = 1'b1;
    assign sd_dat    = 4'hz;
 
-   // USB serial
-   assign tty_rxd   = 1'b1;
-   assign tty_cts   = 1'b1;
-
    // SPI bus (free for ESP32)
    assign spi_clk        = 1'bz;
    assign spi_miso       = 1'bz;
@@ -533,4 +529,16 @@ module max80 (
 
    assign led = led_q;
 
+   // USB serial
+   assign tty_cts   = 1'b0;	// Assert CTS#
+   tty tty (
+	    .rst_n ( rst_n ),
+	    .sys_clk ( sys_clk ),
+	    .tty_clk ( vid_clk ), // 48 MHz
+
+	    .wdata ( cpu_mem_wdata ),
+	    .wstrb ( iodev[1] & cpu_mem_wstrb[0] ),
+
+	    .tty_txd ( tty_rxd ) // DTE -> DCE
+	    );
 endmodule

File diff suppressed because it is too large
+ 1584 - 1527
fpga/output_files/max80.jam


BIN
fpga/output_files/max80.jbc


BIN
fpga/output_files/max80.jic


+ 1 - 1
fpga/output_files/max80.map

@@ -10,7 +10,7 @@ Quad-Serial configuration device dummy clock cycle: 8
 
 Notes:
 
-- Data checksum for this conversion is 0xF76CAFE0
+- Data checksum for this conversion is 0xF77E70CA
 
 - All the addresses in this file are byte addresses
 

BIN
fpga/output_files/max80.pof


BIN
fpga/output_files/max80.sof


+ 131 - 0
fpga/tty.sv

@@ -0,0 +1,131 @@
+//
+// Very simple asynchronous tty. Not really a "UART" since it isn't
+// very "universal". It doesn't have to be.
+//
+// Currently only transmit is supported, 8-N-1, at a fixed speed.
+// The baud rate is tty_clk/((divisor+1)*16).
+//
+// Currently there is no overrun checking or interrupt support, but that
+// can come later. A large FIFO makes that less of an issue anyway...
+//
+
+module tty (
+	    input 	rst_n,
+	    input 	sys_clk,
+	    input 	tty_clk,
+
+	    input [7:0] wdata,
+	    input 	wstrb,
+
+	    output 	tty_txd
+	    );
+   //
+   // Baud rate generator; produces a clock enable synchronous
+   // with tty_clk
+   //
+   parameter [15:0] DIVISOR = 16'd2; // == tty_clk/(3*16)
+   
+   reg [15:0] 		divisor = DIVISOR;
+   reg [15:0] 		clk_div;
+   reg 			tty_clk_en; // tty clock tick (clock enable)
+
+   always @(negedge rst_n or posedge tty_clk)
+     if (~rst_n)
+       begin
+	  clk_div <= 16'h0;
+	  tty_clk_en <= 1'b0;
+       end
+     else
+       begin
+	  if (~|clk_div)
+	    begin
+	       clk_div <= divisor;
+	       tty_clk_en <= 1'b1;
+	    end
+	  else
+	    begin
+	       clk_div <= clk_div - 1'b1;
+	       tty_clk_en <= 1'b0;
+	    end
+       end // else: !if(~rst_n)
+
+   //
+   // Tx FIFO
+   //
+   reg  tx_rdack;
+   wire tx_wrreq;
+   wire tx_rdempty;
+   wire [7:0] tx_data;
+   
+   fifo txfifo (
+		.aclr ( ~rst_n ),
+		.data ( wdata ),
+		.q ( tx_data ),
+		.rdclk ( tty_clk ),
+		.rdreq ( tx_rdack ),
+		.wrclk ( sys_clk ),
+		.wrreq ( tx_wrreq ),
+		.rdempty ( tx_rdempty ),
+		.rdusedw ( ),
+		.wrfull ( ),
+		.wrusedw ( )
+		);
+      
+   //
+   // CPU -> transmitter data. No wait state is needed nor expected.
+   //
+   reg 	      old_wstrb;
+   
+   always @(posedge sys_clk)
+	old_wstrb <= wstrb;
+
+   assign tx_wrreq = wstrb & ~old_wstrb; // Protect against long pulses
+
+   //
+   // Transmitter
+   //
+   reg [3:0]  tx_phase;
+   reg [3:0]  tx_bits;
+   reg [9:0]  tx_sr = ~10'b0;		// Shift register
+   assign tty_txd = tx_sr[0];
+
+   always @(negedge rst_n or posedge tty_clk)
+     if (~rst_n)
+       begin
+	  tx_phase <= 4'h0;
+	  tx_bits  <= 4'd0;
+	  tx_sr    <= ~10'b0;	// Line idle
+	  tx_rdack <= 1'b0;
+       end
+     else
+       begin
+	  tx_rdack <= 1'b0;
+
+	  if ( tty_clk_en )
+	    begin
+	       tx_phase <= tx_phase + 1'b1;
+ 
+	       if (tx_phase == 4'hF)
+		 begin
+		    tx_sr[8:0] <= tx_sr[9:1];
+		    tx_sr[9]   <= 1'b1; // Stop bit/idle
+		    
+		    if (tx_bits == 4'd0)
+		      begin
+			 if ( ~tx_rdempty )
+			   begin
+			      tx_sr[9:2] <= tx_data;
+			      tx_sr[1]   <= 1'b0; // Start bit
+			      // 10 = start bit + data + stop bit
+			      tx_bits    <= 4'd10;
+			      tx_rdack   <= 1'b1; // Remove from FIFO
+			   end
+		      end
+		    else
+		      begin
+			 tx_bits <= tx_bits - 1'b1;
+		      end // else: !if(tx_bits == 4'd0)
+		 end // if (tx_phase == 4'hF)
+	    end // if ( tty_clk_en )
+       end // else: !if(~rst_n)
+endmodule // tty

+ 19 - 6
fw/boot.mif

@@ -9,10 +9,23 @@ CONTENT BEGIN
 002 : 00000000;
 003 : 00000000;
 004 : 0040006F;
-005 : 4781A001;
-006 : 00178713;
-007 : C0F00023;
-008 : 0FF77793;
-009 : BFD5;
-[00A..7FF] : 00;
+005 : 0023A001;
+006 : 0393C000;
+007 : C30304C0;
+008 : 10630003;
+009 : 46B70203;
+00A : 8293000F;
+00B : 12FD2406;
+00C : FE029FE3;
+00D : 00130793;
+00E : 0FF7F313;
+00F : C0600023;
+010 : 0023B7ED;
+011 : 0385C460;
+012 : 0000BFD9;
+013 : 6C6C6548;
+014 : 57202C6F;
+015 : 646C726F;
+016 : 000A0D21;
+[017..7FF] : 00;
 END;

+ 0 - 6
fw/hello.c

@@ -18,11 +18,6 @@ void _start(void)
     const char *p;
     uint8_t led = 0;
 
-    while ( 1 )
-      LED = led++;
-
-#if 0
-
     LED = led = 0;
 
     for (p = hello; *p; p++)
@@ -34,7 +29,6 @@ void _start(void)
 
       LED = ++led;
     }
-#endif
     
     die();
 }

Some files were not shown because too many files changed in this diff