gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

uart_rx.sv (2189B)


      1 // Copyright 2018, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 `default_nettype none
      5 
      6 // Assumes clk is 12M and baudrate is 1M
      7 // TODO: parameterize this a bit
      8 
      9 module uart_rx(
     10 	input clk,
     11 	input rx,
     12 	output [7:0]data,
     13 	output ready,
     14 	output crc_din,
     15 	output crc_en
     16 );	
     17 
     18 // active indicates reception in progress
     19 reg active = 1'b0;
     20 reg active_next;
     21 
     22 // bitcount is a downcounter of bits remaining to receive
     23 reg [2:0]bitcount = 3'd0;
     24 reg [2:0]bitcount_next;
     25 
     26 wire bitcount_done;
     27 wire [2:0]bitcount_minus_one;
     28 assign { bitcount_done, bitcount_minus_one } = { 1'b0, bitcount } - 4'd1;
     29 
     30 // tickcount is a downcounter of sys_clk ticks until next bit
     31 reg [3:0]tickcount = 4'd0;
     32 reg [3:0]tickcount_next;
     33 
     34 wire tick;
     35 wire [3:0]tickcount_minus_one;
     36 assign { tick, tickcount_minus_one }  = { 1'b0, tickcount } - 5'd1;
     37 
     38 // receive shift register
     39 reg [7:0]rxdata;
     40 reg [7:0]rxdata_next;
     41 
     42 // most recent 3 bits for edge detection
     43 reg [2:0]rxedge;
     44 
     45 // drives the ready flag
     46 reg signal = 1'b0;
     47 reg signal_next;
     48 
     49 assign data = rxdata;
     50 assign ready = signal;
     51 
     52 // pass inbound bits to serial crc engine
     53 assign crc_din = rxedge[2];
     54 assign crc_en = active & tick;
     55 
     56 always_comb begin
     57 	signal_next = 1'b0;
     58 	active_next = active;
     59 	bitcount_next = bitcount;
     60 	tickcount_next = tickcount;
     61 	rxdata_next = rxdata;
     62 
     63 	if (active) begin
     64 		if (tick) begin
     65 			rxdata_next = { rxedge[2], rxdata[7:1] };
     66 			if (bitcount_done) begin
     67 				active_next = 1'b0;
     68 				signal_next = 1'b1;
     69 			end else begin
     70 				bitcount_next = bitcount_minus_one;
     71 				// 12 (-1) ticks to the next bit center
     72 				tickcount_next = 4'd11;
     73 			end
     74 		end else begin
     75 			tickcount_next = tickcount_minus_one;
     76 		end
     77 	end else begin
     78 		if (rxedge == 3'b001) begin
     79 			// 12 ticks center to center + 4 to adjust from
     80 			// 2 ticks into the start bit = 16 (-1):
     81 			tickcount_next = 4'd15;
     82 			// 8 (-1) bits to receive:
     83 			bitcount_next = 3'd7;
     84 			// start!
     85 			active_next = 1'b1;
     86 		end
     87 	end
     88 end
     89 
     90 always_ff @(posedge clk) begin
     91 	rxedge <= { rx, active ? 2'b0 : rxedge[2:1] };
     92 	rxdata <= rxdata_next;
     93 	signal <= signal_next;
     94 	active <= active_next;
     95 	bitcount <= bitcount_next;
     96 	tickcount <= tickcount_next;
     97 end
     98 
     99 endmodule