This repository has been archived by the owner on Nov 19, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Peripheral.v
126 lines (119 loc) · 3.36 KB
/
Peripheral.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
module Peripheral(
input reset, sysclk,
input rd,wr,
input [31:0] addr,
input [31:0] wdata,
output reg[31:0] rdata,
input UART_RX,
output UART_TX,
output reg [7:0] led,
input [7:0] switch,
output reg [11:0] digi,
reg irqout,
input PC_31
);
wire gclk;
wire [7:0] TX_DATA;
wire [7:0] RX_DATA;
wire TX_STATUS;
wire RX_STATUS;
reg [7:0] UART_TXD;
reg [7:0] UART_RXD;
reg TX_EN;
reg [31:0] TH, TL;
reg [2:0] TCON;
reg [4:0] UART_CON;
reg isReady;
// assign irqout = (!PC_31)&TCON[2];
assign TX_DATA = UART_TXD;
UART_Receiver x1(RX_STATUS, RX_DATA, sysclk, gclk, UART_RX, reset);
UART_Sender x2(UART_TX, TX_STATUS, TX_EN, TX_DATA, sysclk, gclk, reset);
UART_generator x3(gclk, sysclk, reset);
always @(*) begin
if (rd) begin
case(addr)
32'h40000000: rdata <= TH;
32'h40000004: rdata <= TL;
32'h40000008: rdata <= {29'b0,TCON};
32'h4000000C: rdata <= {24'b0,led};
32'h40000010: rdata <= {24'b0,switch};
32'h40000014: rdata <= {20'b0,digi};
32'h4000001C: rdata <= {24'b0,UART_RXD};
32'h40000020: begin
if(isReady)
rdata <= { 27'b0,5'b1100};
else
rdata <= 32'b0;
end
default: rdata <= 32'b0;
endcase
end
else rdata <= 32'b0;
end
always @(negedge reset or posedge RX_STATUS)
if(~reset)
UART_RXD <= 8'b0000_0000;
else
UART_RXD <= RX_DATA;
always @(negedge reset or posedge sysclk) begin
if (~reset) begin
irqout <= 0;
end else
irqout <= (!PC_31)&TCON[2];
end
always @(negedge reset or posedge sysclk ) begin
if (~reset) begin
TH <= 32'b0;
TL <= 32'b0;
TCON <= 3'b0;
TX_EN <= 0;
UART_CON <= 5'b00000;
UART_TXD <= 8'b0000_0000;
led <= 8'b0000_0000;
isReady <=0;
end
else begin
if (TCON[0]) begin //timer is enabled
if(TL == 32'hffffffff) begin
TL <= TH;
if(TCON[1]) TCON[2] <= 1'b1; //irq is enabled
end
else TL <= TL + 1;
end
if (RX_STATUS) begin //after receiving 8 bits, update state of RXD and CON
UART_CON[3] <= 1;
isReady <=1;
end
if (TX_STATUS) begin //after sending 8 bits, update state of CON
UART_CON[2] <= 1;
UART_CON[4] <= 0;
end
if (TX_EN) //"enable" only lasts for one cycle
TX_EN<=0;
if (rd) //after loading state of CON,clear
if(addr == 32'h40000020 && isReady) begin
UART_CON[2] <= 1'b0;
UART_CON[3] <= 1'b0;
isReady <= 1'b0;
end
if (wr) begin
case(addr)
32'h40000000: TH <= wdata;
32'h40000004: TL <= wdata;
32'h40000008: TCON <= wdata[2:0];
32'h4000000C: led <= wdata[7:0];
32'h40000014: digi <= wdata[11:0];
32'h40000018: begin
UART_TXD <= wdata[7:0];
if (TX_STATUS) begin
TX_EN <= 1;
UART_CON[4] <= 1;
end
end
32'h40000020: UART_CON <= wdata[1:0];
default: ;
endcase
end
end
end
endmodule