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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
module memorio(caddress,address,memread,memwrite,ioread,iowrite,mread_data,ioread_data,wdata,rdata,write_data,LEDCtrl,SwitchCtrl);
input[31:0] caddress; // from alu_result in executs32
input memread; // read memory, from control32
input memwrite; // write memory, from control32
input ioread; // read IO, from control32
input iowrite; // write IO, from control32
input[31:0] mread_data; // data from memory
input[15:0] ioread_data; // data from io,16 bits
input[31:0] wdata; // the data from idecode32,that want to write memory or io
output[31:0] rdata; // data from memory or IO that want to read into register
output[31:0] write_data; // data to memory or I/O
output[31:0] address; // address to mAddress and I/O
output LEDCtrl; // LED CS
output SwitchCtrl; // Switch CS
reg[31:0] write_data;
wire iorw;
assign address = caddress;
assign rdata = (iowrite == 1'b1) ? {16'b0, ioread_data} : memread; // 可能是从memory读出,也可能自io读出,自io读取的数据是rdata的低16bit
assign iorw = (iowrite||ioread);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
assign LEDCtrl = ioread; // led 模块的片选信号,高电平有效;
assign SwitchCtrl = memread; //switch 模块的片选信号,高电平有效
always @* begin
if((memwrite==1)||(iowrite==1)) begin
write_data = wdata;
end else begin
write_data = 32'hZZZZZZZZ;
end
end
endmodule
`timescale 1ns / 1ps
module dmemory32(read_data,address,write_data,Memwrite,clock);
output[31:0] read_data; // 从存储器中获得的数据
input[31:0] address; //来自memorio模块,源头是来自执行单元算出的alu_result
input[31:0] write_data; //来自译码单元的read_data2
input Memwrite; //来自控制单元
input clock;
wire clk;
assign clk = !clock; // 因为使用Block ram的固有延迟,RAM的地址线来不及在时钟上升沿准备好,
// 使得时钟上升沿数据读出有误,所以采用反相时钟,使得读出数据比地址准
// 备好要晚大约半个时钟,从而得到正确地址。
//分配64KB RAM,编译器实际只用 64KB RAM
RAM ram (
.clka(clk), // input wire clka
.wea(Memwrite), // input wire [0 : 0] wea
.addra(address[15:2]), // input wire [13 : 0] addra
.dina(write_data), // input wire [31 : 0] dina
.douta(read_data) // output wire [31 : 0] douta
);
endmodule
module ioread(reset,ior,switchctrl,ioread_data,ioread_data_switch);
input reset; // 复位信号
input ior; // 从控制器来的I/O读,
input switchctrl; // 从memorio经过地址高端线获得的拨码开关模块片选
input[15:0] ioread_data_switch; //从外设来的读数据,此处来自拨码开关
output[15:0] ioread_data; // 将外设来的数据送给memorio
reg[15:0] ioread_data;
always @* begin
if(reset == 1)
ioread_data = 16'b0000000000000000;
else if(ior == 1) begin
if(switchctrl == 1)
ioread_data = ioread_data_switch;
else ioread_data = ioread_data;
end
end
endmodule
module leds(led_clk, ledrst, ledwrite, ledcs, ledaddr,ledwdata, ledout);
input led_clk; // 时钟信号
input ledrst; // 复位信号
input ledwrite; // 写信号
input ledcs; // 从memorio来的,由低至高位形成的LED片选信号 !!!!!!!!!!!!!!!!!
input[1:0] ledaddr; // 到LED模块的地址低端 !!!!!!!!!!!!!!!!!!!!
input[15:0] ledwdata; // 写到LED模块的数据,注意数据线只有16根
output[23:0] ledout; // 向板子上输出的24位LED信号
reg [23:0] ledout;
always@(posedge led_clk or posedge ledrst) begin
if(ledrst) begin
ledout <= 24'h000000;
end
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
else if(ledcs && ledwrite) begin
if(ledaddr == 2'b00)
ledout[23:0] <= { ledout[23:16], ledwdata[15:0] };
else if(ledaddr == 2'b10 )
ledout[23:0] <= { ledwdata[7:0], ledout[15:0] };
else
ledout <= ledout;
end
else begin
ledout <= ledout;
end
end
endmodule
module switchs(switclk, switrst, switchread, switchcs,switchaddr, switchrdata, switch_i);
input switclk; // 时钟信号
input switrst; // 复位信号
input switchcs; //从memorio来的,由低至高位形成的switch片选信号 !!!!!!!!!!!!!!!!!
input[1:0] switchaddr; // 到switch模块的地址低端 !!!!!!!!!!!!!!!
input switchread; // 读信号
output [15:0] switchrdata; // 送到CPU的拨码开关值注意数据总线只有16根
input [23:0] switch_i; // 从板上读的24位开关数据
reg [15:0] switchrdata;
always@(negedge switclk or posedge switrst) begin
if(switrst) begin
switchrdata <= 0;
end
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
else if(switchcs && switchread) begin
if(switchaddr==2'b00)
switchrdata[15:0] <= switch_i[15:0]; // data output,lower 16 bits non-extended
else if(switchaddr==2'b10)
switchrdata[15:0] <= { 8'h00, switch_i[23:16] }; //data output, upper 8 bits extended with zero
else
switchrdata <= switchrdata;
end
else begin
switchrdata <= switchrdata;
end
end
endmodule
module top(clk, rst, ioReadCtrl, MemreadCtrl, iowriteCtrl, ledout, switch_i, MemwriteCtrl,
register, RegAddr, RegwriteCtrl, RegreadCtrl, caddress// );
,ioread_data_switch, write_data, mread_data, ledwdata);
input[31:0] caddress; // 需要写入的地址,在memoryio中赋值给address
input clk, rst;
input ioReadCtrl; // read IO, from control32
input MemreadCtrl; // read memory, from control32
input MemwriteCtrl; // write memory, from control32
input iowriteCtrl; // write IO, from control32
input [23:0] switch_i; // 从板上读的24位开关数据
output[23:0] ledout; // 向板子上输出的24位LED信号
input[4:0] RegAddr;
wire SwitchCtrl;
input RegwriteCtrl, RegreadCtrl;
output [31:0] register[0:31];
wire[15:0] switchrdata; // 送到CPU的拨码开关值注意数据总线只有16根
// 辅助信号
output[15:0] ioread_data_switch;
assign ioread_data_switch = switchrdata;
output[31:0] write_data;
output[31:0] mread_data;
output[15:0] ledwdata;
/* 存储器核心单元 */
wire[31:0] read_data; // 从存储单元中获得的数据
wire LEDCtrl;
wire[31:0] rdata; // data from memory or IO that want to read into register
wire[31:0] address; // address to mAddress and I/O
wire[15:0] ioread_data;
wire[31:0] write_data;
wire[31:0] mread_data = MemreadCtrl ? read_data : (RegreadCtrl ? register[RegAddr] : mread_data);
memorio memorioU(.caddress(caddress),
.address(address),
.memread(MemreadCtrl),
.memwrite(MemwriteCtrl),
.ioread(ioReadCtrl),
.iowrite(iowriteCtrl),
.mread_data(mread_data),
.ioread_data(ioread_data),
.wdata(RegreadCtrl ? register[RegAddr] : 32'b0),
.rdata(rdata),
.write_data(write_data), // data to memory or I/O
.LEDCtrl(LEDCtrl), // led 模块的片选信号,高电平有效;
.SwitchCtrl(SwitchCtrl)); //switch 模块的片选信号,高电平有效
/* 拨码开关 */
/* SwitchCtrl & ioReadCtrl 时可读 */
switchs switchsU(.switclk(clk),
.switrst(rst),
.switchread(ioReadCtrl),
.switchcs(SwitchCtrl),
.switchaddr(address[1:0]),
.switchrdata(switchrdata),
.switch_i(switch_i));
/* IO输入的多路选择器 */
/* ioReadCtrl 时可读, SwitchCtrl 时读取拨码开关 */
ioread ioreadU(.reset(rst),
.ior(ioReadCtrl),
.switchctrl(SwitchCtrl),
.ioread_data(ioread_data),
.ioread_data_switch(switchrdata));
/* 存储单元 */
dmemory32 dmemory32(.read_data(read_data),
.address(address),
.write_data(write_data),
.Memwrite(MemwriteCtrl),
.clock(clk));
/* LED 模块 */
wire[1:0] ledaddr = address[1:0];
wire[15:0] ledwdata = ledaddr == 2'b00 ? mread_data[15:0] : mread_data[31:16]; // 写到LED模块的数据,注意数据线只有16根
leds ledsU(.led_clk(clk),
.ledrst(rst),
.ledwrite(iowriteCtrl),
.ledcs(LEDCtrl),
.ledaddr(ledaddr),
.ledwdata(ledwdata),
.ledout(ledout));
/* 内置寄存器 */
reg [31:0] register[0:31];
always@(posedge clk, negedge rst) begin
if (rst) begin
for (integer cnt = 0; cnt < 32; cnt = cnt + 1)
register[cnt] <= 0;
end
else if (RegwriteCtrl == 1'b1) begin
if (address[1:0] == 2'b00)
register[RegAddr][15:0] <= ioread_data;
else
register[RegAddr][31:16] <= ioread_data;
end
end
endmodule
|