Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix#45 #48

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion j1a/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,10 @@ mackextload:

endif

.PHONY: connect clean bootstrap mackextload mackextunload macconnect
pcon:
$(info Use C-a C-t to toggle reset line as necessary)
$(info Use C-a C-x to exit. No shell.py features are available)
picocom -b 921600 /dev/ttyUSB1 --imap lfcrlf,crcrlf --omap delbs,crlf --send-cmd "ascii-xfr -s -l 30 -n"


.PHONY: connect sim_connect j4a_sim_connect clean bootstrap mackextload mackextunload macconnect linmodload pcon
6 changes: 3 additions & 3 deletions j1a/icestorm/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
VERILOGS = j1a.v uart.v ../verilog/j1.v ../verilog/stack2.v
VERILOGS = j1a.v async_in_filter.v uart3.v ../verilog/j1.v ../verilog/stack2.v

VERILOGS8k = j1a8k.v uart.v ../verilog/j1.v ../verilog/stack2.v
VERILOGS8k = j1a8k.v uart3.v async_in_filter.v ../verilog/j1.v ../verilog/stack2.v

VERILOGS8k4 = j4a.v uart.v ../verilog/j1.v ../verilog/stack2.v ../verilog/j4.v ../verilog/stack2pipe4.v ../verilog/greycount.v
VERILOGS8k4 = j4a.v uart3.v async_in_filter.v ../verilog/*.v

SUBDIRS = ..

Expand Down
46 changes: 46 additions & 0 deletions j1a/icestorm/async_in_filter.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module async_in_filter (
input wire clk,
input wire pin,
output reg rd);
// This module is intended to accept up to a maximum 750 kHz async signal,
// and synchronise it safely to a 48 MHz clock.
// It will add at least 27 clks of latency, and may not respond reliably to a 1MHz signal.
wire onereg;
SB_IO #(.PIN_TYPE(6'b0000_00)) inpin (
.PACKAGE_PIN(pin),
.CLOCK_ENABLE(1'b1),
.INPUT_CLK(clk),
.D_IN_0(onereg));
reg threereg, tworeg; always @(posedge clk) {threereg,tworeg} <= {tworeg,onereg};
// triple registering helps prevent metastability when synchronising an undefined signal into a clock domain.
parameter FILTERBITS = 5;
// Final part is somewhat of a digital moving average glitch filter, with a digital Schmidt trigger output.
// this one takes 24 ticks to set rd on.
// saturates after 31 sequential highs.
// Then will take 24 sequential lows to turn off.
// Saturating back on zero after the 31st.
reg [FILTERBITS-1:0] fltr;
wire [1:0] tops = fltr[FILTERBITS-1:FILTERBITS-2]; // top two bits are used to decide whether to change output state.
// change the two above to change the timing.
// (increase fltr size for slower signals,
// decrease for faster. should be no less than three bits.)
wire incr = ~&fltr & threereg;
wire decr = |fltr & ~threereg;
wire setr = &tops;
wire clrr = ~|tops;
always @(posedge clk)
begin
case({incr,decr})
10: fltr <= fltr + 1;
01: fltr <= fltr - 1;
default: fltr <= fltr;
endcase
case({setr,clrr})
10: rd <= 1'b1;
01: rd <= 1'b0;
default: rd <= rd;
endcase
end

endmodule

Binary file modified j1a/icestorm/j1a.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions j1a/icestorm/j1a.v
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ module top(input pclk, output D1, output D2, output D3, output D4, output D5,
wire uart0_wr = io_wr_ & io_addr_[12];
wire uart0_rd = io_rd_ & io_addr_[12];
wire uart_RXD;
inpin _rcxd(.clk(clk), .pin(RXD), .rd(uart_RXD));
buart _uart0 (
async_in_filter _rcxd(.clk(clk), .pin(RXD), .rd(uart_RXD));
buart #(.BAUD(921600)) _uart0 (
.clk(clk),
.resetq(1'b1),
.rx(uart_RXD),
Expand Down
Binary file modified j1a/icestorm/j1a8k.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions j1a/icestorm/j1a8k.v
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ module top(input pclk,
wire uart0_wr = io_wr_ & io_addr_[12];
wire uart0_rd = io_rd_ & io_addr_[12];
wire uart_RXD;
inpin _rcxd(.clk(clk), .pin(RXD), .rd(uart_RXD));
buart _uart0 (
async_in_filter _rcxd(.clk(clk), .pin(RXD), .rd(uart_RXD));
buart #(.BAUD(921600)) _uart0 (
.clk(clk),
.resetq(1'b1),
.rx(uart_RXD),
Expand Down
Binary file modified j1a/icestorm/j4a.bin
Binary file not shown.
4 changes: 2 additions & 2 deletions j1a/icestorm/j4a.v
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,8 @@ module top(input pclk,
wire uart0_wr = io_wr_ & io_addr_[12];
wire uart0_rd = io_rd_ & io_addr_[12];
wire uart_RXD;
inpin _rcxd(.clk(clk), .pin(RXD), .rd(uart_RXD));
buart _uart0 (
async_in_filter _rcxd(.clk(clk), .pin(RXD), .rd(uart_RXD));
buart #(.BAUD(921600)) _uart0 (
.clk(clk),
.resetq(1'b1),
.rx(uart_RXD),
Expand Down
69 changes: 69 additions & 0 deletions j1a/icestorm/uart3.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
`default_nettype none

module buart(
input clk, // The master clock for this module
input resetq, // Synchronous reset, active low
input rx, // Incoming serial line
output tx, // Outgoing serial line
input rd, // read strobe -- used only to clear valid flag.
input wr, // write strobe
output reg valid, // Indicates a new byte is available. clears on read.
output reg busy, // Low when transmit line is idle.
input [7:0] tx_data, // Byte to transmit
output reg [7:0] rx_data, // *Most recent* byte received -- whether or not the last was collected.
output reg error // reception error
);
// you can override these on a per-port basis, looks like:
// buart #(.BAUD(115200)) _youruart (.clk(clk)...etc);
// or
// buart #(.CLOCK_DIVIDE(312)) _uart1 (...
// The latter might be better for designs with non-48MHz clocks.
parameter BAUD = 9600;
parameter CLKFREQ = 48000000; // frequency of incoming signal 'clk'
parameter CLOCK_DIVIDE = (CLKFREQ / (BAUD * 4)); // clock rate (48Mhz) / (baud rate (460800) * 4)
// will probably want to support at least down to 9600 baud, which will require a CLOCK_DIVIDE == 1250

localparam CDSIZE = $clog2(CLOCK_DIVIDE)+1; // one more to accomodate assumed signed arithmatic
reg [5:0] bytephase;
reg [CDSIZE-1:0] rxclkcounter;
wire rxqtick = rxclkcounter == CLOCK_DIVIDE; // strobes high one clk every 1/4 bit time
wire rxrst = rx & (~|bytephase); // rx goes low with the beginning of the start bit. synchronous to system clk, not sample clk.
always @(posedge clk) rxclkcounter <= rxrst | rxqtick ? 1 : rxclkcounter + 1; // initially held in reset
// very important: idle rx line holds rxrst asserted,
// this goes on *until* the start edge is found.
// thus synchronising further sampling to that edge, rather than remaining in phase with however it was reset.

wire rxstop = bytephase == 6'd40; // 11th sample 'tick' would have been at 42.
wire nonstarter;
always @(posedge clk) bytephase <= rxstop|nonstarter ? 0 : rxqtick ? bytephase + 1 : bytephase;
wire sample = (bytephase[1:0] == 2'b10) & rxqtick; // one clk for each of ten bits
// note sample is false while rxrst is true.
assign nonstarter = (bytephase == 6'd2) & rx; // start bit should still be low when sample strobes first.
// if it isn't, then it will go back to a rxrst state.

// after this point, we have a sample strobe, a rxstop strobe
reg [9:0] capture; always @(posedge clk) capture <= sample ? {rx, capture[9:1]} : capture;
// note bits are sent least-significant first.
wire startbit = capture[0]; // valid when rxstop strobes, and until rxrst releases for the next byte.
wire stopbit = capture[9];
wire good = stopbit&~startbit; // valid when rxstop is asserted. stop bit should be 1, start bit should have been zero.
always @(posedge clk)
begin
valid <= rd ? 1'b0 : rxstop & good ? 1'b1 : valid;
rx_data <= rxstop & good ? capture[8:1] : rx_data;
error <= nonstarter ? 1'b1 : rxstop ? ~good : error ;
end
// tx parts
reg [CDSIZE+1:0] txclkcounter; // note, two extra bits to accomodate a limit 4x as large.
wire txtick = txclkcounter == 4*CLOCK_DIVIDE; // ticks for a clk once every bit, not every quarter bit.
always @(posedge clk) txclkcounter <= txtick ? 1 : txclkcounter + 1;
// note txclkcounter never needs to be reset out-of-phase with itself.
reg [3:0] sentbits;
wire done = sentbits == 4'd10; // eventually stays 'done'. Reset to zero again when wr strobes.
always @(posedge clk) sentbits <= txtick & ~done ? sentbits + 1 : wr ? 4'd0 : sentbits ;
reg [9:0] sender;
// wr strobe might come any clk, not synchronous to txtick. No real need to force txtick to be synchronous to it either.
always @(posedge clk) sender <= wr ? {tx_data, 1'b0, 1'b1} : txtick ? {1'b1, sender[9:1]} : sender;
assign tx = sender[0]; // wr loads this 1, because tranmission doesn't start until the next txtick, whenever it arrives.
assign busy = ~done;
endmodule
2 changes: 1 addition & 1 deletion j1a/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def open_ser(self, port, speed):
except:
print("This tool needs PySerial, but it was not found")
sys.exit(1)
self.ser = serial.Serial(port, 4 * 115200, timeout=None, rtscts=0)
self.ser = serial.Serial(port, 921600, timeout=None, rtscts=0)

def reset(self, fullreset = True):
ser = self.ser
Expand Down