OpenCores
URL https://opencores.org/ocsvn/raptor64/raptor64/trunk

Subversion Repositories raptor64

[/] [raptor64/] [trunk/] [rtl/] [verilog/] [SimpleMMU.v] - Rev 52

Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
//=============================================================================
//        __
//   \\__/ o\    (C) 2011,2012  Robert Finch
//    \  __ /    All rights reserved.
//     \/_//     robfinch<remove>@opencores.org
//       ||
//  
//	SimpleMMU.v
//  - maps 128MB into 512 256kB blocks
//  - supports 32 tasks per mmu
//  
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
//                                                                          
// This source file 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/>.    
//                                                                          
//
// 20 block RAMs // 106 LUTs // 42 FF's // 190 MHz
//=============================================================================
//
module SimpleMMU(num, rst_i, clk_i, dma_i, kernel_mode, cyc_i, stb_i, ack_o, we_i, adr_i, dat_i, dat_o, rclk, pc_i, pc_o, ea_i, ea_o);
parameter pIOAddress = 24'hDC4000;
input [2:0] num;		// mmu number
input rst_i;			// core reset
input clk_i;			// clock
input dma_i;			// 1=DMA cycle is active
input kernel_mode;		// 1=processor is in kernel mode
input cyc_i;			// bus cycle active
input stb_i;			// data transfer strobe
output ack_o;			// data transfer acknowledge
input we_i;				// write enable
input [23:0] adr_i;		// I/O register address
input [15:0] dat_i;		// data input
output [15:0] dat_o;	// data output
reg [15:0] dat_o;
input rclk;				// read clock (~clk)
input [27:0] pc_i;		// program counter / instruction pointer input
output [27:0] pc_o;		// mapped version of program counter
reg [27:0] pc_o;
input [27:0] ea_i;		// effective data address input
output [27:0] ea_o;		// effective data address mapped
reg [27:0] ea_o;
 
reg map_enable;
reg forceHi;
reg su;					// 1= system
reg [3:0] fuse;
reg ofuse3;
reg [7:0] accessKey;
reg [7:0] operateKey;
reg [2:0] kvmmu;
reg ack1, ack2;
 
always @(posedge clk_i)
begin
	ack1 <= cs;
	ack2 <= ack1 & cs;
end
assign ack_o = cs ? (we_i ? 1'b1 : ack2) : 1'b0;
 
wire cs = cyc_i && stb_i && (adr_i[23:12]==pIOAddress[23:12]);
wire [7:0] oKey =
	dma_i ? 8'd1 :
	su ? 8'd0 :
	operateKey
	;
reg [13:0] rmrad;
reg [13:0] rmra;
reg [13:0] rmrb;
wire [13:0] mwa = {accessKey[4:0],adr_i[9:1]};
wire [13:0] mrad = {accessKey[4:0],adr_i[9:1]};
wire [13:0] mra = {oKey[4:0],pc_i[26:18]};
wire [13:0] mrb = {oKey[4:0],ea_i[26:18]};
wire [9:0] mro0,mro1,mro2;
 
always @(posedge clk_i) rmrad <= mrad;
always @(posedge rclk) rmra <= mra;
always @(posedge rclk) rmrb <= mrb;
wire thisMMU = kvmmu==accessKey[7:5];
 
wire pe_stb;
wire pe_km;
edge_det u1 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(stb_i), .pe(pe_stb), .ne(), .ee() );
edge_det u2 (.rst(rst_i), .clk(clk_i), .ce(1'b1), .i(kernel_mode), .pe(pe_km), .ne(), .ee() );
 
mapram u3
(
	.wclk(clk_i),
	.wr(cs & we_i & su & ~adr_i[10] & thisMMU),
	.wa(mwa),
	.i(dat_i[9:0]),
	.rclk(~clk_i),
	.ra0(mrad),
	.ra1(mra),
	.ra2(mrb),
	.o0(mro0),
	.o1(mro1),
	.o2(mro2)
);
 
always @(posedge clk_i)
if (rst_i) begin
	map_enable <= 1'b0;
	kvmmu <= 3'd0;
	su <= 1'b1;
	fuse <= 4'hF;
	ofuse3 <= 1'b1;
	accessKey <= 8'h00;
	operateKey <= 8'h00;
end
else begin
	ofuse3 <= fuse[3];
	if (!fuse[3] && !dma_i && pe_stb)
		fuse <= fuse - 4'd1;
	if (fuse[3] & !ofuse3)
		su <= 1'b0;
	else if (pe_km)
		su <= 1'b1;
 
	if (cs) begin
		if (we_i) begin
			if (su) begin
				casex(adr_i[10:0])
//				11'b0xxxxxxxxxx:	if (thisMMU) map[mwa] <= dat_i[9:0];
				11'h40x:	if (oKey==8'h00 && (adr_i[2:0]==num))
									kvmmu <= dat_i[2:0];
				11'h412:	fuse <= dat_i[2:0];
				11'h414:	accessKey <= dat_i[7:0];
				11'h416:	operateKey <= dat_i[7:0];
				11'h418:	map_enable <= dat_i[0];
				endcase
			end
		end
		else begin
			if ((adr_i[2:0]==num) && oKey==8'd0 && adr_i[10:4]==7'b1000000)
				dat_o <= {5'd0,kvmmu};
			else if (thisMMU)
				casex(adr_i[10:0])
				11'b0xxxxxxxxxx:	dat_o <= mro0;
				11'h410:	dat_o <= su;
				11'h412:	dat_o <= fuse;
				11'h414:	dat_o <= accessKey;
				11'h416:	dat_o <= operateKey;
				11'h418:	dat_o <= map_enable;
				default:	dat_o <= 16'h0000;
				endcase
			else
				dat_o <= 16'h0000;
		end
	end
	else
		dat_o <= 16'h0000;
end
 
always @(pc_i) pc_o[17:0] <= pc_i[17:0];
always @(ea_i) ea_o[17:0] <= ea_i[17:0];
 
always @(rmra or oKey or kvmmu or mro1 or cs or map_enable)
begin
	if (!map_enable)
		pc_o[27:18] <= pc_i[27:18];
	else if (kvmmu==oKey[7:5])
		pc_o[27:18] <= mro1;
	else
		pc_o[27:18] <= 10'h000;
end
 
always @(rmrb or oKey or kvmmu or mro2 or cs or cyc_i or ea_i or map_enable)
begin
	if (cyc_i|~map_enable)		// I/O cycles are not mapped
		ea_o[27:18] <= ea_i[27:18];
	else if (kvmmu==oKey[7:5])
		ea_o[27:18] <= mro2;
	else
		ea_o[27:18] <= 10'h000;
end
 
endmodule
 
module mapram(wclk, wr, wa, i, rclk, ra0, ra1, ra2, o0, o1, o2);
input wclk;
input wr;
input [13:0] wa;
input [9:0] i;
input rclk;
input [13:0] ra0;
input [13:0] ra1;
input [13:0] ra2;
output [9:0] o0;
output [9:0] o1;
output [9:0] o2;
 
reg [9:0] map [0:16383];
reg [13:0] rra0,rra1,rra2;
 
always @(posedge wclk)
	if (wr) map[wa] <= i;
always @(posedge rclk) rra0 <= ra0;
always @(posedge rclk) rra1 <= ra1;
always @(posedge rclk) rra2 <= ra2;
 
assign o0 = map[rra0];
assign o1 = map[rra1];
assign o2 = map[rra2];
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.