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