9086/system/memory.v
(Tim) Efthimis Kritikos 1966ab78b4 Peripherals/I2C: Added a CPU I2C driver and wrote a bootloader that uses that to boot from an I2C eeprom
I'm happy to have reached 200 commits and with this, version v0.3.0 is functionally ready. I still need to do a fair bit of cleanup and bug fixing though before the actual release. With this commit I added a CPU I2C driver as well as a basic arbiter to have the hardware lcd controller and the software i2c communication pass through the same I2C driver and I2C bus. I also wrote a bootloader that reads code from an i2c eeprom to make sure the hardware works.
2024-02-09 23:30:58 +00:00

75 lines
2.3 KiB
Verilog

/* memory.v - implementation of memory external to the 9086 CPU for testing purposes
This file is part of the 9086 project.
Copyright (c) 2023 Efthymios Kritikos
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* This warning is because we don't use the full address bus. */
/* verilator lint_off UNUSEDSIGNAL */
module doublemem
#(
parameter RAM_SIZE_IN_BYTES,
parameter ADDRESS_WIDTH=$clog2(RAM_SIZE_IN_BYTES)
)
( input [ ADDRESS_WIDTH-1 : 0 ] address,
output [15:0] cpu_read_data,
input [15:0] cpu_write_data,
input rd,
input wr,
input BHE,
input cs,
input clock
);
/* verilator lint_on UNUSEDSIGNAL */
reg [15:0] memory [0:(RAM_SIZE_IN_BYTES/2)-1];
initial begin
`ifndef YOSYS
string boot_code;
if(!$value$plusargs("BOOT_CODE=%s",boot_code))begin
$display("No boot code specified. Please add +BOOT_CODE=<path> to your vvp args");
$finish;
end
$readmemh(boot_code, memory,0,(RAM_SIZE_IN_BYTES/2)-1);
`else
//TODO: don't have it hard coded
$readmemh("../boot_code/i2c_bootloader.stxt", memory,0,(RAM_SIZE_IN_BYTES/2)-1); // 2KiB
`endif
end
`ifdef USE_HIGH_IMPEDANCE
assign cpu_read_data[7:0] = !address[0:0] & !rd & !cs ? memory[address[ADDRESS_WIDTH-1:1]][15:8] : `16'hz;
assign cpu_read_data[15:8] = !BHE & !rd & !cs ? memory[address[ADDRESS_WIDTH-1:1]][ 7:0] : `16'hz;
`else
assign cpu_read_data[7:0] = memory[address[ADDRESS_WIDTH-1:1]][15:8];
assign cpu_read_data[15:8] = memory[address[ADDRESS_WIDTH-1:1]][ 7:0];
`endif
always @(posedge clock) begin
if( cs == 0 && wr == 0) begin
if(BHE==0)
memory[address[ADDRESS_WIDTH-1:1]][7:0]<=cpu_write_data[15:8];
if(address[0]==0)
memory[address[ADDRESS_WIDTH-1:1]][15:8]<=cpu_write_data[7:0];
end
end
endmodule