-
Notifications
You must be signed in to change notification settings - Fork 0
/
UART_rcv.sv
109 lines (85 loc) · 1.84 KB
/
UART_rcv.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
module UART_rcv(clk , rst_n ,clr_rdy , rx_data, rdy, RX);
input clk, RX, rst_n , clr_rdy;
output [7:0] rx_data;
output reg rdy;
typedef enum logic {IDLE , RCVNG} state_t;
logic start, shift ,receiving;
logic [3:0] bit_cnt;
logic [3:0] nxt_bit_cnt;
logic [11:0] baud_cnt;
logic [11:0] nxt_baud_cnt;
logic [8:0] shift_reg;
logic [8:0] nxt_shift_reg;
always_comb begin
priority case ({start,shift}) inside
2'b1x: nxt_bit_cnt = '0;
2'b01: nxt_bit_cnt = bit_cnt + 1;
2'b00: nxt_bit_cnt = bit_cnt;
endcase
end
always_ff @(posedge clk) begin
bit_cnt <= nxt_bit_cnt;
end
always_comb begin
priority case ({(start || shift),receiving}) inside
2'b1x: begin
if(start == 1)
nxt_baud_cnt = 12'h516;
else
nxt_baud_cnt = 12'hA2C;
end
2'b01: nxt_baud_cnt = baud_cnt - 1;
2'b00: nxt_baud_cnt = baud_cnt;
endcase
end
always_ff @(posedge clk) begin
baud_cnt <= nxt_baud_cnt;
end
assign shift = (baud_cnt === 12'h000)?1'b1:1'b0;
always_comb begin
priority case (shift) inside
1'b1: nxt_shift_reg = {RX,shift_reg[8:1]};
1'b0: nxt_shift_reg = shift_reg;
endcase
end
always_ff @(posedge clk) begin
shift_reg <= nxt_shift_reg;
end
assign rx_data = shift_reg[7:0];
state_t state, nxt_state;
logic set_rdy ;
always_comb begin
nxt_state = state;
receiving= 0;
set_rdy = 0;
unique case(state)
IDLE: if(start) begin
nxt_state = RCVNG;
end
RCVNG: begin
receiving = 1;
if(bit_cnt === 4'b1010) begin
set_rdy = 1;
nxt_state = IDLE;
end
end
endcase
end
assign start = (state == IDLE && RX == 0)?1'b1:1'b0;
always_ff @(posedge clk, negedge rst_n) begin
if(!rst_n)
state <= IDLE;
else
state <= nxt_state;
end
always_ff @(posedge clk, negedge rst_n) begin
if(!rst_n)
rdy <= 1'b0;
else begin
if(start | clr_rdy)
rdy <= 1'b0;
else if(set_rdy)
rdy <= 1'b1;
end
end
endmodule