-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathloader.v
executable file
·158 lines (145 loc) · 6.15 KB
/
loader.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
155
156
157
158
/**************************************************************************************************/
/**** RVSoc (Mini Kuroda/RISC-V) since 2018-08-07 ArchLab. TokyoTech ****/
/**** ALU Module v0.01 ****/
/**************************************************************************************************/
`default_nettype none
/**************************************************************************************************/
`include "define.vh"
/**************************************************************************************************/
/* Clock Interval Definition */
/**************************************************************************************************/
// b = baud rate (in Mbps)
// f = frequency of the clk for the processor core (in MHz)
// SERIAL_WCNT = f/b
// e.g. b = 1, f = 50 -> SERIAL_WCNT = 50/1 = 50
//`ifndef SERIAL_WCNT
//`define SERIAL_WCNT 10 // 1M baud UART wait count, 8 for 64MHz, 9 for 72MHz
//`endif
/**************************************************************************************************/
/* Program Loader: Initialize the main memory, copy memory image to the main memory */
/**************************************************************************************************/
module PLOADER (CLK, RST_X, RXD, ADDR, DATA, WE, DONE, KEY_WE, KEY_DATA);
input wire CLK, RST_X, RXD;
output reg [31:0] ADDR;
output reg [31:0] DATA;
output reg WE;
output reg DONE; // program load is done
output wire KEY_WE;
output wire [7:0] KEY_DATA;
reg [31:0] waddr=0; // memory write address
wire SER_EN;
wire [7:0] SER_DATA;
serialc serc (CLK, RST_X, RXD, SER_DATA, SER_EN);
assign KEY_WE = SER_EN && DONE;
assign KEY_DATA = SER_DATA;
always @(posedge CLK) begin
if(!RST_X) begin
ADDR <= 0;
DATA <= 0;
WE <= 0;
waddr <= 0;
`ifdef BYPASS_PLOADER
DONE <= 1;
`else
DONE <= 0;
`endif
end else begin
if(DONE==0 && SER_EN) begin
ADDR <= waddr;
//ADDR <= (waddr<32'h40000) ? waddr : {8'h04, 6'd0, waddr[17:0]};
DATA <= {SER_DATA, DATA[31:8]};
WE <= (waddr[1:0]==3);
waddr <= waddr + 1;
end else begin
WE <= 0;
if(waddr>=`BIN_SIZE) DONE <= 1;
end
end
end
endmodule
/**************************************************************************************************/
module UartTx(CLK, RST_X, DATA, WE, TXD, READY);
input wire CLK, RST_X, WE;
input wire [7:0] DATA;
output reg TXD, READY;
reg [8:0] cmd;
reg [31:0] waitnum;
reg [3:0] cnt;
always @(posedge CLK) begin
if(!RST_X) begin
TXD <= 1'b1;
READY <= 1'b1;
cmd <= 9'h1ff;
waitnum <= 0;
cnt <= 0;
end else if( READY ) begin
TXD <= 1'b1;
waitnum <= 0;
if( WE )begin
`ifdef SIM_MODE
$write("%c", DATA);
`ifndef VERILATOR
$fflush();
`endif
`endif
READY <= 1'b0;
cmd <= {DATA, 1'b0};
cnt <= 10;
end
end else if( waitnum >= `SERIAL_WCNT ) begin
//$display("tx sending..");
TXD <= cmd[0];
READY <= (cnt == 1);
cmd <= {1'b1, cmd[8:1]};
waitnum <= 1;
cnt <= cnt - 1;
end else begin
waitnum <= waitnum + 1;
end
end
endmodule
/**************************************************************************************************/
/* RS232C serial controller (deserializer): */
/**************************************************************************************************/
`define SS_SER_WAIT 'd0 // RS232C deserializer, State WAIT
`define SS_SER_RCV0 'd1 // RS232C deserializer, State Receive 0th bit
// States Receive 1st bit to 7th bit are not used
`define SS_SER_DONE 'd9 // RS232C deserializer, State DONE
/**************************************************************************************************/
module serialc(CLK, RST_X, RXD, DATA, EN);
input wire CLK, RST_X, RXD; // clock, reset, RS232C input
output [7:0] DATA; // 8bit output data
output reg EN; // 8bit output data enable
reg [7:0] DATA;
reg [3:0] stage;
reg [12:0] cnt; // counter to latch D0, D1, ..., D7
reg [11:0] cnt_start; // counter to detect the Start Bit
wire [12:0] waitcnt;
assign waitcnt = `SERIAL_WCNT;
always @(posedge CLK) begin
if (!RST_X) cnt_start <= 0;
else cnt_start <= (RXD) ? 0 : cnt_start + 1;
end
always @(posedge CLK) begin
if(!RST_X) begin
EN <= 0;
stage <= `SS_SER_WAIT;
cnt <= 1;
DATA <= 0;
end else if (stage == `SS_SER_WAIT) begin // detect the Start Bit
EN <= 0;
stage <= (cnt_start == (waitcnt >> 1)) ? `SS_SER_RCV0 : stage;
end else begin
if (cnt != waitcnt) begin
cnt <= cnt + 1;
EN <= 0;
end else begin // receive 1bit data
stage <= (stage == `SS_SER_DONE) ? `SS_SER_WAIT : stage + 1;
EN <= (stage == 8) ? 1 : 0;
DATA <= {RXD, DATA[7:1]};
cnt <= 1;
end
end
end
endmodule
/**************************************************************************************************/