-
Notifications
You must be signed in to change notification settings - Fork 80
/
Copy pathsimulation.v
156 lines (139 loc) · 3.05 KB
/
simulation.v
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
`timescale 1ns / 1ps
module uart_simu();
reg clk = 0;
initial begin
forever #5 clk = ~clk;
end
reg btn1 = 0;
reg btn2 = 0;
wire btn3;
wire btn4;
wire led;
wire tx;
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, top_inst);
btn1 = 1;
#130
btn1 = 0;
#3000000
$finish;
end
always @ (posedge clk) begin
btn2 <= ~btn2;
end
assign btn3 = 1;
assign btn4 = 0;
//top top_inst(
chip top_inst(
.clk(clk),
.btn1(btn1),
.btn2(btn2),
.btn3(btn3),
.btn4(btn4),
.led(led),
.tx(tx)
);
wire rxclk_en;
uart_rx uart_rx_inst(
.clk(clk),
.rxclk_en(rxclk_en),
.rx(tx)
);
baud_rate_gen baud_rate_gen_inst(
.clk(clk),
.rxclk_en(rxclk_en)
);
endmodule
module uart_rx
(
input clk,
input rxclk_en,
input rx,
output newrecv,
output [7:0]charrecv
);
localparam RX_STATE_START = 2'b01;
localparam RX_STATE_DATA = 2'b10;
localparam RX_STATE_STOP = 2'b11;
reg [1:0]state_rx = RX_STATE_START;
reg [3:0]sample = 0;
reg [3:0]bitpos_rx = 0;
reg [7:0]scratch = 8'b0;
reg [7:0]data_rx = 0;
assign charrecv = data_rx;
reg data_rx_ready = 0;
reg data_rx_ready_old = 0;
always @ (posedge clk) begin
data_rx_ready_old <= data_rx_ready;
end
assign newrecv = !data_rx_ready_old & data_rx_ready;
always @ (posedge clk) begin if (rxclk_en) begin
case(state_rx)
RX_STATE_START: begin
data_rx_ready <= 0;
if (!rx || sample != 0) sample <= sample + 1;
if (sample == 15) begin
state_rx <= RX_STATE_DATA;
bitpos_rx <= 0;
sample <= 0;
scratch <= 0;
end
end
RX_STATE_DATA: begin
sample <= sample + 1;
if (sample == 8) begin //
scratch[bitpos_rx[2:0]] <= rx;
bitpos_rx <= bitpos_rx + 1;
end
if (bitpos_rx == 8 && sample == 15) state_rx <= RX_STATE_STOP;
end
RX_STATE_STOP: begin
if (sample == 15 || (sample >= 8 && !rx)) begin //
$display("%c", scratch);
state_rx <= RX_STATE_START;
data_rx <= scratch;
data_rx_ready <= 1;
sample <= 0;
end else begin
sample <= sample + 1;
end
end
default: state_rx <= RX_STATE_START;
endcase
end end
endmodule
module baud_rate_gen
#(
parameter CLOCK_FREQ = 30000000,
parameter BAUD_RATE = 115200,
parameter SAMPLE_MULTIPLIER = 16
)
(
input wire clk,
output wire rxclk_en,
output wire txclk_en
);
parameter RX_ACC_MAX = CLOCK_FREQ / (BAUD_RATE * SAMPLE_MULTIPLIER);
parameter TX_ACC_MAX = CLOCK_FREQ / BAUD_RATE;
parameter RX_ACC_WIDTH = 16;
parameter TX_ACC_WIDTH = 16;
//parameter RX_ACC_WIDTH = $clog2(RX_ACC_MAX);
//parameter TX_ACC_WIDTH = $clog2(TX_ACC_MAX);
reg [RX_ACC_WIDTH - 1:0] rx_acc = 0;
reg [TX_ACC_WIDTH - 1:0] tx_acc = 0;
assign rxclk_en = (rx_acc == 0);
assign txclk_en = (tx_acc == 0);
always @(posedge clk) begin
if (rx_acc == RX_ACC_MAX[RX_ACC_WIDTH - 1:0])
rx_acc <= 0;
else
rx_acc <= rx_acc + 1;
end
always @(posedge clk) begin
if (tx_acc == TX_ACC_MAX[TX_ACC_WIDTH - 1:0])
tx_acc <= 0;
else
tx_acc <= tx_acc + 1;
end
endmodule