blob: 175f9d6f0af5fc4dc46e9574ceba5192a18bcbc1 [file] [log] [blame]
/****************************************************************************
* fwrisc_fpga_top.sv
*
* Copyright 2018 Matthew Ballance
*
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in
* writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See
* the License for the specific language governing
* permissions and limitations under the License.
*
****************************************************************************/
/**
* Module: fwrisc_fpga_top
*
* TODO: Add module documentation
*/
module fwrisc_fpga_top (
input clock,
output clock_o,
output led0,
output led1,
output tx,
output d0_p,
output d0_n);
wire reset;
wire iaddr_ok;
wire idata_ok;
reg[1:0] clk_cnt;
// /4 clock divider
always @(posedge clock)
clk_cnt <= clk_cnt + 1;
wire clock4 = clk_cnt[1];
assign clock_o = clock4;
reg[15:0] reset_cnt;
reg[15:0] reset_key;
always @(posedge clock4) begin
if (reset_key != 16'ha520) begin
reset_key <= 16'ha520;
reset_cnt <= 16'h0000;
end else if (reset_cnt != 1000) begin
reset_cnt <= reset_cnt + 1;
end
end
assign reset = (reset_key != 16'ha520 || reset_cnt != 1000);
wire[31:0] iaddr;
reg[31:0] idata;
wire ivalid;
wire iready;
wire[31:0] daddr;
wire[31:0] dwdata;
reg[31:0] drdata;
wire[3:0] dwstb;
wire dwrite;
wire dvalid;
wire dready;
fwrisc u_core (
.clock (clock4 ),
.reset (reset ),
.iaddr (iaddr ),
.idata (idata ),
.ivalid (ivalid ),
.iready (iready ),
.daddr (daddr ),
.dwdata (dwdata ),
.drdata (drdata ),
.dwstb (dwstb ),
.dwrite (dwrite ),
.dvalid (dvalid ),
.dready (dready ));
// ROM: 'h8000_0000
// RAM: 'h8000_8000
// LED: 'hC000_0000
reg[7:0] ram_0[1023:0]; // 16k ram
reg[7:0] ram_1[1023:0]; // 16k ram
reg[7:0] ram_2[1023:0]; // 16k ram
reg[7:0] ram_3[1023:0]; // 16k ram
reg[31:0] rom[4095:0]; // 16k rom
reg[31:0] led;
reg[31:0] tx_r;
reg iready_r, dready_r;
assign iready = iready_r;
assign dready = dready_r;
assign d0_p = iaddr_ok; // iaddr[4]; // clk_cnt[0]; // iaddr[2]; // led[1];
assign d0_n = led[3]; //data_ok; // clk_cnt[1]; // iaddr[3]; // led[2];
assign tx = tx_r[0];
assign led0 = led[0];
assign led1 = led[1];
initial begin
$readmemh("rom.hex", rom);
end
reg[31:0] addr_d;
reg[31:0] addr_i;
always @(posedge clock4) begin
addr_d <= daddr;
addr_i <= iaddr;
if (dvalid && dready && dwrite) begin
if (daddr[31:28] == 4'h8 &&
daddr[15:12] == 4'h8) begin
// $display("Write to RAM: 'h%08h", daddr[13:2]);
if (dwstb[0]) ram_0[daddr[13:2]] <= dwdata[7:0];
if (dwstb[1]) ram_1[daddr[13:2]] <= dwdata[15:8];
if (dwstb[2]) ram_2[daddr[13:2]] <= dwdata[23:16];
if (dwstb[3]) ram_3[daddr[13:2]] <= dwdata[31:24];
end else if (daddr[31:28] == 4'hc) begin
if (daddr[3:2] == 4'h0) begin
led <= dwdata;
end else if (daddr[3:2] == 4'h1) begin
tx_r <= dwdata;
end
end
end
end
always @(posedge clock4) begin
// Prefer data access
if (dvalid) begin
dready_r <= 1;
iready_r <= 0;
end else if (ivalid) begin
iready_r <= 1;
dready_r <= 0;
end else begin
iready_r <= 0;
dready_r <= 0;
end
end
always @* begin
if (addr_d[31:28] == 4'h8 && addr_d[15:12] == 4'h8) begin
drdata = {
ram_3[addr_d[13:2]],
ram_2[addr_d[13:2]],
ram_1[addr_d[13:2]],
ram_0[addr_d[13:2]]
};
/*
$display("read 'h%08h 'h%0h", addr_d[13:2],
{ram_3[addr_d[13:2]],
ram_2[addr_d[13:2]],
ram_1[addr_d[13:2]],
ram_0[addr_d[13:2]]
});
*/
end else begin
drdata = rom[addr_d[13:2]];
end
if (addr_i[31:28] == 4'h8 && addr_i[15:12] == 4'h8) begin
idata = {
ram_3[addr_d[13:2]],
ram_2[addr_d[13:2]],
ram_1[addr_d[13:2]],
ram_0[addr_d[13:2]]
};
end else begin
idata = rom[addr_i[13:2]];
end
end
endmodule