Skip to content
Snippets Groups Projects
Commit 7e1605b9 authored by Byron Lathi's avatar Byron Lathi
Browse files

Merge branch 'mmu' into 'master'

Add memory mapper.

See merge request !10
parents e7defb71 0752cc4b
No related branches found
No related tags found
1 merge request!10Add memory mapper.
Pipeline #137 passed
......@@ -38,3 +38,10 @@ test-sw:
script:
- cd sw/
- make test
test_mm:
stage: test
image: bslathi19/modelsim_18.1:lite
script:
- cd hw/fpga/simulation/modelsim/
- vsim -do "do mm_testbench.do"
module addr_decode(
input logic [15:0] addr,
input logic [23:0] addr,
output logic sdram_cs,
output logic rom_cs,
output logic hex_cs,
output logic uart_cs,
output logic irq_cs,
output logic board_io_cs
output logic board_io_cs,
output logic mm_cs1,
output logic mm_cs2
);
assign rom_cs = addr >= 16'h8000;
assign sdram_cs = addr < 16'h7ff0;
assign hex_cs = addr >= 16'h7ff0 && addr < 16'h7ff4;
assign uart_cs = addr >= 16'h7ff4 && addr < 16'h7ff6;
assign board_io_cs = addr == 16'h7ff6;
assign irq_cs = addr == 16'h7fff;
assign rom_cs = addr >= 24'h008000 && addr < 24'h010000;
assign sdram_cs = addr < 24'h007fe0 || addr >= 24'h010000;
assign mm_cs1 = addr >= 24'h007fe0 && addr < 24'h007ff0;
assign hex_cs = addr >= 24'h007ff0 && addr < 24'h007ff4;
assign uart_cs = addr >= 24'h007ff4 && addr < 24'h007ff6;
assign board_io_cs = addr == 24'h007ff6;
assign mm_cs2 = addr == 24'h007ff7;
assign irq_cs = addr == 24'h007fff;
endmodule
......@@ -4,27 +4,29 @@ timeunit 10ns;
timeprecision 1ns;
logic [15:0] addr;
logic [23:0] addr;
logic sdram_cs;
logic rom_cs;
logic hex_cs;
logic board_io_cs;
logic uart_cs;
logic irq_cs;
logic mm_cs2;
logic mm_cs1;
int cs_count = sdram_cs + rom_cs + hex_cs + uart_cs + board_io_cs;
int cs_count = sdram_cs + rom_cs + hex_cs + uart_cs + board_io_cs + mm_cs2 + mm_cs1;
addr_decode dut(.*);
initial begin : TEST_VECTORS
for (int i = 0; i < 2**16; i++) begin
for (int i = 0; i < 2**24; i++) begin
addr <= i;
#1
assert(cs_count < 2)
else
$error("Multiple chip selects present!");
if (i < 16'h7ff0) begin
if (i < 16'h7fe0 || i >= 24'h010000) begin
assert(sdram_cs == '1)
else
$error("Bad CS! addr=%4x should have sdram_cs!", addr);
......@@ -44,12 +46,22 @@ initial begin : TEST_VECTORS
else
$error("Bad CS! addr=%4x should have board_io_cs!", addr);
end
if (i == 16'h7ff7) begin
assert(mm_cs2 == '1)
else
$error("Bad CS! addr=%4x should have mm_cs2!", addr);
end
if (i >= 16'h7fe0 && i < 16'h7ff0) begin
assert(mm_cs1 == '1)
else
$error("Bad CS! addr=%4x should have mm_cs1!", addr);
end
if (i == 16'h7fff) begin
assert(irq_cs == '1)
else
$error("Bad CS! addr=%4x should have irq_cs!", addr);
end
if (i >= 2**15) begin
if (i >= 2**15 && i < 24'h010000) begin
assert(rom_cs == '1)
else
$error("Bad CS! addr=%4x should have rom_cs!", addr);
......
module testbench();
timeunit 10ns;
timeprecision 1ns;
logic clk_50, clk, cs;
logic rw, MM_cs;
logic rst;
logic [3:0] RS, MA;
logic [7:0] data_in;
logic [7:0] data_out;
logic [11:0] MO;
logic [11:0] _data_in;
assign _data_in = {4'h0, data_in};
logic [11:0] _data_out;
assign data_out = _data_out[7:0];
logic [15:0] cpu_addr;
logic [23:0] mm_address;
assign MA = cpu_addr[15:12];
assign mm_address = {MO, cpu_addr[11:0]};
memory_mapper dut(
.data_in(_data_in),
.data_out(_data_out),
.*
);
always #1 clk_50 = clk_50 === 1'b0;
always #100 clk = clk === 1'b0;
task write_reg(logic [3:0] addr, logic [7:0] data);
@(negedge clk);
cs <= '1;
RS <= addr;
data_in <= data;
rw <= '0;
@(posedge clk);
cs <= '0;
rw <= '1;
@(negedge clk);
endtask
task enable(logic [7:0] data);
@(negedge clk);
MM_cs <= '1;
rw <= '0;
data_in <= data;
@(posedge clk);
rw <= '1;
MM_cs <= '0;
@(negedge clk);
endtask
initial begin
rst <= '1;
repeat(5) @(posedge clk);
rst <= '0;
cpu_addr <= 16'h0abc;
write_reg(4'h0, 8'hcc);
$display("Address: %x", mm_address);
assert(mm_address == 24'h000abc) else begin
$error("Bad address before enable!");
end
enable(1);
$display("Address: %x", mm_address);
assert(mm_address == 24'h0ccabc) else begin
$error("Bad address after enable!");
end
enable(0);
$display("Address: %x", mm_address);
assert(mm_address == 24'h000abc) else begin
$error("Bad address after enable!");
end
$finish();
end
endmodule
/*
* This is based off of the 74LS610, but is not identical.
Some of the inputs are flipped so that they are all active high,
and some outputs are reordered.
Notably, when MM is low, MA is present on MO0-MO4, not 8 to 11.
*/
module memory_mapper(
input clk,
input rst,
input rw,
input cs,
input MM_cs,
input [3:0] RS,
input [3:0] MA,
input logic [11:0] data_in,
output logic [11:0] data_out,
output logic [11:0] MO
);
logic [11:0] RAM [16];
logic MM;
always_ff @(posedge clk) begin
if (rst) begin
MM <= '0;
end else begin
if (MM_cs & ~rw) begin // can't read MM but do you really need too?
MM = |data_in;
end
if (cs & ~rw) begin // write to registers
RAM[RS] <= data_in;
end else if (cs & rw) begin // read registers
data_out <= RAM[RS];
end
end
end
always_comb begin
if (MM) begin // normal mode
MO = RAM[MA];
end else begin // passthrough mode
MO = {8'b0, MA};
end
end
endmodule
......@@ -2,7 +2,7 @@ module sdram(
input rst,
input clk_50,
input cpu_clk,
input [15:0] addr,
input [23:0] addr,
input sdram_cs,
input rwb,
input [7:0] data_in,
......@@ -84,4 +84,4 @@ sdram_platform u0 (
.sdram_wire_we_n(DRAM_WE_N) //.we_n
);
endmodule
\ No newline at end of file
endmodule
transcript on
if {[file exists rtl_work]} {
vdel -lib rtl_work -all
}
vlib rtl_work
vmap work rtl_work
vlog -sv -work work {../../memory_mapper.sv}
vlog -sv -work work {../../hvl/mm_testbench.sv}
vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L stratixv_ver -L stratixv_hssi_ver -L stratixv_pcie_hip_ver -L rtl_work -L work -voptargs="+acc" testbench
add wave -group {dut} -radix hexadecimal sim:/testbench/dut/*
onfinish stop
run -all
if { [coverage attribute -name TESTSTATUS -concise] == "1"} {
echo Warning
quit -f -code 0
}
quit -code [coverage attribute -name TESTSTATUS -concise]
......@@ -350,6 +350,7 @@ set_location_assignment PIN_V22 -to DRAM_LDQM
set_location_assignment PIN_U22 -to DRAM_RAS_N
set_location_assignment PIN_J21 -to DRAM_UDQM
set_location_assignment PIN_V20 -to DRAM_WE_N
set_global_assignment -name SYSTEMVERILOG_FILE memory_mapper.sv
set_global_assignment -name SYSTEMVERILOG_FILE board_io.sv
set_global_assignment -name SYSTEMVERILOG_FILE sdram.sv
set_global_assignment -name QIP_FILE sdram_platform/synthesis/sdram_platform.qip
......
......@@ -3,15 +3,15 @@ module super6502(
input clk_50,
input logic rst_n,
input logic button_1,
input logic [15:0] cpu_addr,
inout logic [7:0] cpu_data,
input logic cpu_vpb,
input logic cpu_mlb,
input logic cpu_rwb,
input logic cpu_sync,
output logic cpu_led,
output logic cpu_resb,
output logic cpu_rdy,
......@@ -20,9 +20,9 @@ module super6502(
output logic cpu_phi2,
output logic cpu_be,
output logic cpu_nmib,
output logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5,
input logic UART_RXD,
output logic UART_TXD,
......@@ -42,7 +42,7 @@ module super6502(
output DRAM_CAS_N,
output DRAM_RAS_N
);
logic rst;
assign rst = ~rst_n;
......@@ -60,6 +60,7 @@ logic [7:0] sdram_data_out;
logic [7:0] uart_data_out;
logic [7:0] irq_data_out;
logic [7:0] board_io_data_out;
logic [7:0] mm_data_out;
logic sdram_cs;
logic rom_cs;
......@@ -67,6 +68,8 @@ logic hex_cs;
logic uart_cs;
logic irq_cs;
logic board_io_cs;
logic mm_cs1;
logic mm_cs2;
cpu_clk cpu_clk(
.inclk0(clk_50),
......@@ -84,14 +87,34 @@ assign cpu_be = '1;
assign cpu_nmib = '1;
assign cpu_irqb = irq_data_out == 0;
logic [11:0] mm_MO;
logic [23:0] mm_addr;
assign mm_addr = {mm_MO, cpu_addr[11:0]};
memory_mapper memory_mapper(
.clk(clk),
.rst(rst),
.rw(cpu_rwb),
.cs(mm_cs1),
.MM_cs(mm_cs2),
.RS(cpu_addr[3:0]),
.MA(cpu_addr[15:12]),
.data_in(cpu_data_in),
.data_out(mm_data_out),
.MO(mm_MO)
);
addr_decode decode(
.addr(cpu_addr),
.addr(mm_addr),
.sdram_cs(sdram_cs),
.rom_cs(rom_cs),
.hex_cs(hex_cs),
.uart_cs(uart_cs),
.irq_cs(irq_cs),
.board_io_cs(board_io_cs)
.board_io_cs(board_io_cs),
.mm_cs1(mm_cs1),
.mm_cs2(mm_cs2)
);
......@@ -106,6 +129,8 @@ always_comb begin
cpu_data_out = irq_data_out;
else if (board_io_cs)
cpu_data_out = board_io_data_out;
else if (mm_cs1)
cpu_data_out = mm_data_out;
else
cpu_data_out = 'x;
end
......@@ -115,7 +140,7 @@ sdram sdram(
.rst(rst),
.clk_50(clk_50),
.cpu_clk(cpu_phi2),
.addr(cpu_addr),
.addr(mm_addr),
.sdram_cs(sdram_cs),
.rwb(cpu_rwb),
.data_in(cpu_data_in),
......@@ -193,6 +218,6 @@ always_ff @(posedge clk_50) begin
end
end
endmodule
\ No newline at end of file
......@@ -8,4 +8,7 @@ UART_STATUS = UART + 1
LED = $7ff6
SW = LED
MM_CTRL = $7ff7
MM_DATA = $7fe0
IRQ_STATUS = $7fff
......@@ -3,6 +3,7 @@
#include "board_io.h"
#include "uart.h"
#include "mapper.h"
int main() {
int i;
......@@ -13,6 +14,38 @@ int main() {
clrscr();
cprintf("Hello, world!\n");
for (i = 0; i < 16; i++){
cprintf("Mapping %1xxxx to %2xxxx\n", i, i);
mapper_write(i, i);
}
cprintf("Enabling Mapper\n");
mapper_enable(1);
cprintf("Writing 0xcccc to 0x4000\n");
*(unsigned int*)(0x4000) = 0xcccc;
cprintf("Writing 0xdddd to 0x5000\n");
*(unsigned int*)(0x5000) = 0xdddd;
cprintf("Mapping %1xxxx to %2xxxx\n", 4, 16);
mapper_write(16, 4);
cprintf("Mapping %1xxxx to %2xxxx\n", 5, 16);
mapper_write(16, 5);
cprintf("Writing 0xa5a5 to 0x4000\n");
*(unsigned int*)(0x4000) = 0xa5a5;
cprintf("Reading from 0x5000: %x\n", *(unsigned int*)(0x5000));
cprintf("Resetting map\n");
mapper_write(4, 4);
mapper_write(5, 5);
cprintf("Reading from 0x4000: %x\n", *(unsigned int*)(0x4000));
cprintf("Reading from 0x5000: %x\n", *(unsigned int*)(0x5000));
while (1) {
sw = sw_read();
......
#ifndef _MAPPER_H
#define _MAPPER_H
#include <stdint.h>
void mapper_enable(uint8_t en);
uint8_t mapper_read(uint8_t addr);
void mapper_write(uint8_t data, uint8_t addr);
#endif
.include "io.inc65"
.importzp sp, sreg
.export _mapper_enable
.export _mapper_read, _mapper_write
.autoimport on
.code
; void mapper_enable(uint8_t en)
_mapper_enable:
sta MM_CTRL
rts
_mapper_read:
phx
tax
lda MM_DATA,x
ldx #$00
rts
_mapper_write:
phx
tax
jsr popa
sta MM_DATA,x
plx
rts
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment