UART传输协议实现

FPGA上的UART协议。

RX端的时钟是16×波特率TX端则是等于波特率

本代码数据格式: 1 起始 8 数据 1 结束

RX端代码


clk - 时钟

rst - 重置 低有效

din - 接收信号线

srecv - 读取信号 上升沿触发

data - 接收数据

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
module uart_rx(
input clk,
input rst,
input din,
output reg srecv = 0,
output reg [7:0] data = 0);

reg [3:0] count = 0;
reg [1:0] state = 0;
reg [2:0] i = 0;

always @ (posedge clk, negedge rst) begin
if(~rst) begin
count <= 0;
i <= 0;
srecv <= 0;
data <= 0;
state <= 2'h0;
end
else begin
case(state)
2'h0: begin
if(din == 0)
if(count != 15)
count <= count + 1;
else begin
count <= 0;
state <= 2'h1;
srecv <= 0;
end
else
count <= 0;
end

2'h1: begin
if(count != 15) begin
count <= count + 1;
if(count == 10) begin
data[i] <= din;
end
end
else begin
count <= 0;

if(i == 7)
state <= 2'h2;

i <= i + 1;
end
end

2'h2: begin
if(count != 15)
count <= count + 1;
else begin
count <= 0;
state <= 2'h0;
srecv <= 1;
end
end

endcase
end
end

endmodule

TX端代码


clk - 时钟

rst - 重置 低有效

ssend - 发送信号 上升沿触发

data - 发送数据

send - 发送状态 高为正在发送

dout - 发送信号线

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
module uart_tx(
input clk,
input rst,
input ssend,
input [7:0] data,
output reg send = 0,
output reg dout = 1);

reg [1:0] state = 2'h2;
reg [7:0] sdata = 0;
reg [3:0] i = 0;

reg last_check = 0;
reg check = 0;

always @ (posedge ssend, negedge rst) begin
if(~rst) begin
sdata <= 0;
check <= 0;
end
else begin
sdata <= data;
check <= ~check;
end
end

always @ (posedge clk, negedge rst) begin
if(~rst) begin
i <= 0;
dout = 1;
state <= 2'h2;
last_check = 0;
end
else begin
if(check != last_check) begin
state <= 2'h0;
last_check = check;
end

case(state)
2'h0: begin
send <= 1;
dout = 0;
state <= 2'h1;
end

2'h1: begin
dout = sdata[i];

if(i != 7) begin
i <= i + 1;
end
else begin
i <= 0;
state <= 2'h2;
end
end

2'h2: begin
dout = 1;
send <= 0;
end

endcase
end
end

endmodule

Verilog分频器与数码管

暑期课又在做FPGA了。

每次都写一遍分频器真的挺费事的,所以干脆现在给它记下来。

分频器


可以用于奇分频偶分频

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
module mydivider(
input clk,
input reset,
output dclk);

parameter width = 3;
parameter n = 5;

reg dclk_p, dclk_n;

reg [width-1:0] count_p = 0;
reg [width-1:0] count_n = 0;

always @ (posedge clk, negedge reset) begin
if(~reset) begin
count_p <= 0;
dclk_p <= 0;
end
else begin
count_p <= count_p + 1;
case(count_p)
n/2-1: dclk_p <= 0;
n-1: begin
dclk_p <= 1;
count_p <= 0;
end
default: dclk_p <= dclk_p;
endcase
end
end

always @ (negedge clk, negedge reset) begin
if(~reset) begin
count_n <= 0;
dclk_n <= 0;
end
else begin
count_n <= count_n + 1;
case(count_n)
n/2-1: dclk_n <= 0;
n-1: begin
dclk_n <= 1;
count_n <= 0;
end
default: dclk_n <= dclk_n;
endcase
end
end

assign dclk = n%2 == 1 ? dclk_p | dclk_n : dclk_p;

endmodule

数码管 共阳


没有的数码管代码(问就是板子没连,我也不知道为啥…

记录这个纯属是不想再写一遍这些管子的的亮灭了。

16个case分别对应0 - F的显示。

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
module nixietube(
input [3:0] data,
output reg [6:0] show);

always begin
case(data[3:0])
4'd0: show <= 7'b1000000;
4'd1: show <= 7'b1111001;
4'd2: show <= 7'b0100100;
4'd3: show <= 7'b0110000;
4'd4: show <= 7'b0011001;
4'd5: show <= 7'b0010010;
4'd6: show <= 7'b0000010;
4'd7: show <= 7'b1111000;
4'd8: show <= 7'b0000000;
4'd9: show <= 7'b0010000;
4'd10: show <= 7'b0001000;
4'd11: show <= 7'b0000011;
4'd12: show <= 7'b1000110;
4'd13: show <= 7'b0100001;
4'd14: show <= 7'b0000110;
4'd15: show <= 7'b0001110;
default: show <= 7'b1000000;
endcase
end

endmodule

「向着星辰与深渊」