URL
https://opencores.org/ocsvn/minirisc/minirisc/trunk
Subversion Repositories minirisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/verilog/testbench/prog_mem.v
0,0 → 1,52
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Synchrounous Program Memory //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 10ps |
|
// For simulation only |
// May be off or on chip |
|
module prog_mem ( clk, address, we, din, dout ); |
|
input clk; |
input [10:0] address; |
input we; |
input [11:0] din; |
output [11:0] dout; |
|
parameter depth = 2048; |
|
reg [10:0] addr_r; |
reg [11:0] mem[0:depth-1]; |
|
always @(posedge clk) |
addr_r <= address; |
|
assign dout = mem[addr_r]; |
|
always @(posedge clk) |
if (we) mem[address] <= din; |
|
endmodule |
/trunk/verilog/core/primitives.v
0,0 → 1,203
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Primitives //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 10ps |
|
// Mux 4:1 8 bits wide |
module mux4_8(sel, in0, in1, in2, in3, out); |
input [1:0] sel; |
input [7:0] in0, in1, in2, in3; |
output [7:0] out; |
|
reg [7:0] out; |
|
always @(sel or in0 or in1 or in2 or in3) |
case(sel) |
0: out = in0; |
1: out = in1; |
2: out = in2; |
3: out = in3; |
endcase |
|
endmodule |
|
// 8 bit comparator |
module cmp8_eq(a,b,eq); |
input [7:0] a,b; |
output eq; |
|
assign eq = (a==b); |
|
endmodule |
|
// MUX 2:1 7 bits wide |
module mux2_7(sel, in0, in1, out); |
input sel; |
input [6:0] in0, in1; |
output [6:0] out; |
|
assign out = sel ? in1 : in0; |
|
endmodule |
|
// Mux 8:1 1 bit wide |
module mux8_1( sel, in, out); |
input [2:0] sel; |
input [7:0] in; |
output out; |
|
assign out = in[sel]; |
|
endmodule |
|
// Mux 2:1 8 bits wide |
module mux2_8(sel, in0, in1, out); |
input sel; |
input [7:0] in0, in1; |
output [7:0] out; |
|
assign out = sel ? in1 : in0; |
|
endmodule |
|
// Mux 8:1 8 bits wide |
module mux8_8(sel, in0, in1, in2, in3, in4, in5, in6, in7, out); |
input [2:0] sel; |
input [7:0] in0, in1, in2, in3, in4, in5, in6, in7; |
output [7:0] out; |
|
reg [7:0] out; |
|
always @(sel or in0 or in1 or in2 or in3 or in4 or in5 or in6 or in7) |
case(sel) |
3'd0: out = in0; |
3'd1: out = in1; |
3'd2: out = in2; |
3'd3: out = in3; |
3'd4: out = in4; |
3'd5: out = in5; |
3'd6: out = in6; |
3'd7: out = in7; |
endcase |
|
endmodule |
|
// Mux 2:1 11 bits wide |
module mux2_11(sel, in0, in1, out); |
input sel; |
input [10:0] in0, in1; |
output [10:0] out; |
|
assign out = sel ? in1 : in0; |
|
endmodule |
|
|
// 8bit Add/Sub with carry/borrow out |
module add_sub8_co(sub, opa, opb, out, co); |
input sub; |
input [7:0] opa, opb; |
output [7:0] out; |
output co; |
|
assign {co, out} = sub ? (opa - opb) : (opa + opb); |
|
endmodule |
|
// 11 bit incrementer |
module inc11(in, out); |
input [10:0] in; |
output [10:0] out; |
|
assign out = in + 1; |
|
endmodule |
|
// 8 bit incrementer |
module inc8(in, out); |
input [7:0] in; |
output [7:0] out; |
|
assign out = in + 1; |
|
endmodule |
|
// A Basic Synchrounous FIFO (4 entries deep) |
module sfifo4x11(clk, push, din, pop, dout); |
input clk; |
input push; |
input [10:0] din; |
input pop; |
output [10:0] dout; |
|
reg [10:0] stack1, stack2, stack3, stack4; |
|
assign dout = stack1; |
|
always @(posedge clk) |
begin |
if(push) // PUSH stack |
begin |
stack4 <= #1 stack3; |
stack3 <= #1 stack2; |
stack2 <= #1 stack1; |
stack1 <= #1 din; |
end |
if(pop) // POP stack |
begin |
stack1 <= #1 stack2; |
stack2 <= #1 stack3; |
stack3 <= #1 stack4; |
end |
end |
|
endmodule |
|
|
// Synchrounous SRAM |
// 128 bytes by 8 bits |
// 1 read port, 1 write port |
module ssram_128x8(clk, rd_addr, rd_data, we, wr_addr, wr_data); |
input clk; |
input [6:0] rd_addr; |
output [7:0] rd_data; |
input we; |
input [6:0] wr_addr; |
input [7:0] wr_data; |
|
reg [7:0] rf_mem[0:128]; // Actual Memory |
|
reg [7:0] rd_data; |
|
always @(posedge clk) // Synchrounous Read Logic |
rd_data <= #1 rf_mem[rd_addr]; |
|
always @(posedge clk) // Synchrounous Write Logic |
if(we) |
rf_mem[wr_addr] <= #1 wr_data; |
|
endmodule |
|
|
/trunk/verilog/core/test.v
0,0 → 1,295
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Primitives for Xilinx Virtex Famaly //// |
//// (Generated with CoreGen) //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 10ps |
|
module test; |
|
reg clk; |
reg reset; |
reg tcki; |
|
// Declare I/O Port connections |
wire [7:0] porta; // I/O Port A |
wire [7:0] portb; // I/O Port B |
wire [7:0] portc; // I/O Port C |
|
wire [7:0] portain; |
wire [7:0] portbin; |
wire [7:0] portcin; |
|
wire [7:0] portaout; |
wire [7:0] portbout; |
wire [7:0] portcout; |
|
wire [7:0] trisa; |
wire [7:0] trisb; |
wire [7:0] trisc; |
|
// Declare ROM and rom signals |
wire [10:0] inst_addr; |
wire [11:0] inst_data; |
|
|
always #10 clk = ~clk; |
always #20 tcki = ~tcki; |
|
// Instantiate one CPU to be tested. |
mrisc u0( |
.clk (clk), |
.rst_in (reset), |
.inst_addr (inst_addr), |
.inst_data (inst_data), |
|
.portain (portain), |
.portbin (portbin), |
.portcin (portcin), |
|
.portaout (portaout), |
.portbout (portbout), |
.portcout (portcout), |
|
.trisa (trisa), |
.trisb (trisb), |
.trisc (trisc), |
|
.tcki (tcki), |
.wdt_en (1'b1) |
|
); |
|
// IO buffers for IO Ports |
assign porta = trisa ? 8'bz : portaout; |
assign portain = porta; |
|
assign portb = trisb ? 8'bz : portbout; |
assign portbin = portb; |
|
assign portc = trisc ? 8'bz : portcout; |
assign portcin = portc; |
|
// Pullups for IO Ports |
pullup ua0(porta[0]); |
pullup ua1(porta[1]); |
pullup ua2(porta[2]); |
pullup ua3(porta[3]); |
pullup ua4(porta[4]); |
pullup ua5(porta[5]); |
pullup ua6(porta[6]); |
pullup ua7(porta[7]); |
|
pullup ub0(portb[0]); |
pullup ub1(portb[1]); |
pullup ub2(portb[2]); |
pullup ub3(portb[3]); |
pullup ub4(portb[4]); |
pullup ub5(portb[5]); |
pullup ub6(portb[6]); |
pullup ub7(portb[7]); |
|
pullup uc0(portc[0]); |
pullup uc1(portc[1]); |
pullup uc2(portc[2]); |
pullup uc3(portc[3]); |
pullup uc4(portc[4]); |
pullup uc5(portc[5]); |
pullup uc6(portc[6]); |
pullup uc7(portc[7]); |
|
|
|
// Instantiate the Program RAM. |
prog_mem u1 ( |
.clk (clk), |
.address (inst_addr), |
.we (1'b0), // This testbench doesn't allow writing to PRAM |
.din (12'b000000000000), // This testbench doesn't allow writing to PRAM |
.dout (inst_data) |
); |
|
// This is the only initial block in the test module and this is where |
// you select what test you want to do. |
|
initial |
begin |
$display ("\n\nMini-RISC. Version 1.0\n\n"); |
|
//$dumpfile ("mini-risc.vcd"); |
//$dumpvars (0, test); |
|
clk = 0; |
tcki = 0; |
|
sanity1; |
|
$readmemh ("scode/sanity2.rom", u1.mem); run_code("Sanity 2 "); |
|
$readmemh ("scode/rf1.rom", u1.mem); run_code("Register File 1 "); |
|
$readmemh ("scode/rf2.rom", u1.mem); run_code("Register File 2 "); |
|
$readmemh ("scode/rf3.rom", u1.mem); run_code("Register File 3 "); |
|
//$readmemh ("scode/tmr_wdt.rom", u1.mem); run_code("Timer / WDT "); |
|
//$dumpflush; |
$finish; |
end |
|
|
task sanity1; |
|
`define GOOD 12'h0aa |
`define BAD 12'h0af |
`define SANITY1 "scode/sanity1.rom" |
|
begin |
$display ("========== Starting Sanity 1 Test ========== \n"); |
reset = 1; |
repeat(10) @(posedge clk); |
reset = 0; |
|
//$display ("Loading program memory with %s", `SANITY1); |
$readmemh (`SANITY1, u1.mem); |
while(inst_addr != `GOOD & inst_addr != `BAD) @(posedge clk); |
|
if(inst_addr == `GOOD) |
begin |
$display("Sanity1 test PASSED !!!"); |
end |
else |
if(inst_addr == `BAD) |
begin |
$display("Sanity1 test FAILED !!!"); |
end |
else |
$display("Sanity1 test status UNKNOWN !!!"); |
|
|
repeat(4) @(posedge clk); |
$display("=============================================\n\n\n"); |
|
end |
endtask |
|
task run_code; |
input [16*8-1:0] str; |
|
|
begin |
$display ("========== Starting %s Test ========== \n",str); |
reset = 1; |
repeat(10) @(posedge clk); |
reset = 0; |
|
//$display ("Loading program memory with %s", `SANITY2); |
//$readmemh (`SANITY2, u1.mem); |
|
repeat(10) @(posedge clk); |
while(porta == 8'h00) @(posedge clk); |
|
|
if(porta == 8'h01) |
begin |
$display("Test %s PASSED !!!",str); |
end |
else |
if(porta == 8'hff) |
begin |
$display("Test %s FAILED in test %d !!!", str, portb); |
end |
else |
$display("Test %s status UNKNOWN (%h test: %d) !!!", str, porta, portb); |
|
|
repeat(4) @(posedge clk); |
$display("\n=============================================\n\n\n"); |
|
end |
endtask |
|
/* |
always @(posedge clk) |
if(!reset) |
begin |
if( |u0.w ===1'bx ) $display("%t: Warning :W went unknown",$time); |
if( |u0.pc ===1'bx ) $display("%t: Warning :PC went unknown",$time); |
if( |u0.status ===1'bx ) $display("%t: Warning :STATUS went unknown",$time); |
end |
*/ |
|
reg [8*8-1:0] inst_string; |
|
always @(inst_data) begin |
casex (inst_data) |
12'b0000_0000_0000: inst_string = "NOP "; |
12'b0000_001X_XXXX: inst_string = "MOVWF "; |
12'b0000_0100_0000: inst_string = "CLRW "; |
12'b0000_011X_XXXX: inst_string = "CLRF "; |
12'b0000_10XX_XXXX: inst_string = "SUBWF "; |
12'b0000_11XX_XXXX: inst_string = "DECF "; |
12'b0001_00XX_XXXX: inst_string = "IORWF "; |
12'b0001_01XX_XXXX: inst_string = "ANDWF "; |
12'b0001_10XX_XXXX: inst_string = "XORWF "; |
12'b0001_11XX_XXXX: inst_string = "ADDWF "; |
12'b0010_00XX_XXXX: inst_string = "MOVF "; |
12'b0010_01XX_XXXX: inst_string = "COMF "; |
12'b0010_10XX_XXXX: inst_string = "INCF "; |
12'b0010_11XX_XXXX: inst_string = "DECFSZ "; |
12'b0011_00XX_XXXX: inst_string = "RRF "; |
12'b0011_01XX_XXXX: inst_string = "RLF "; |
12'b0011_10XX_XXXX: inst_string = "SWAPF "; |
12'b0011_11XX_XXXX: inst_string = "INCFSZ "; |
|
// *** Bit-Oriented File Register Operations |
12'b0100_XXXX_XXXX: inst_string = "BCF "; |
12'b0101_XXXX_XXXX: inst_string = "BSF "; |
12'b0110_XXXX_XXXX: inst_string = "BTFSC "; |
12'b0111_XXXX_XXXX: inst_string = "BTFSS "; |
|
// *** Literal and Control Operations |
12'b0000_0000_0010: inst_string = "OPTION "; |
12'b0000_0000_0011: inst_string = "SLEEP "; |
12'b0000_0000_0100: inst_string = "CLRWDT "; |
12'b0000_0000_0101: inst_string = "TRIS "; |
12'b0000_0000_0110: inst_string = "TRIS "; |
12'b0000_0000_0111: inst_string = "TRIS "; |
12'b1000_XXXX_XXXX: inst_string = "RETLW "; |
12'b1001_XXXX_XXXX: inst_string = "CALL "; |
12'b101X_XXXX_XXXX: inst_string = "GOTO "; |
12'b1100_XXXX_XXXX: inst_string = "MOVLW "; |
12'b1101_XXXX_XXXX: inst_string = "IORLW "; |
12'b1110_XXXX_XXXX: inst_string = "ANDLW "; |
12'b1111_XXXX_XXXX: inst_string = "XORLW "; |
|
default: inst_string = "-XXXXXX-"; |
endcase |
//$display("Executing[%h] %s",inst_addr, inst_string); |
end |
|
|
endmodule |
|
/trunk/verilog/core/alu.v
0,0 → 1,120
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// ALU //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 10ps |
|
module alu(s1, s2, mask, out, op, c_in, c, dc, z); |
input [7:0] s1, s2, mask; |
output [7:0] out; |
input [3:0] op; |
input c_in; |
output c, dc, z; |
|
parameter ALU_ADD = 4'h0, |
ALU_SUB = 4'h1, |
ALU_INC = 4'h2, |
ALU_DEC = 4'h3, |
|
ALU_AND = 4'h4, |
ALU_CLR = 4'h5, |
ALU_NOT = 4'h6, |
ALU_IOR = 4'h7, |
ALU_MOV = 4'h8, |
ALU_MOVW = 4'h9, |
ALU_RLF = 4'ha, |
ALU_RRF = 4'hb, |
ALU_SWP = 4'hc, |
ALU_XOR = 4'hd, |
ALU_BCF = 4'he, |
ALU_BSF = 4'hf; |
|
wire [7:0] out; |
wire co, bo; |
wire c; |
wire z; |
wire [5:0] tmp_add; |
wire borrow_dc; |
|
wire [7:0] add_sub_out; |
wire add_sub_sel; |
wire [7:0] s2_a; |
wire [8:0] rlf_out, rrf_out; |
wire [7:0] out_next1, out_next2, out_next3; |
|
/* |
reg cout; |
reg [7:0] out_t; |
always @(op or s1 or s2 or mask or c_in) |
begin |
cout = 0; |
case(op) // synopsys full_case parallel_case |
ALU_ADD: {cout, out} = s1 + s2; |
ALU_AND: out_t = s1 & s2; |
ALU_CLR: out_t = 8'h00; |
ALU_NOT: out_t = ~s1; |
ALU_DEC: out_t = s1 - 1; |
ALU_INC: out_t = s1 + 1; |
ALU_IOR: out_t = s1 | s2; |
ALU_MOV: out_t = s1; |
ALU_MOVW: out_t = s2; |
ALU_RLF: {cout, out_t} = {s1[7:0], c_in}; |
ALU_RRF: {cout, out_t} = {s1[0], c_in, s1[7:1]}; |
ALU_SUB: {cout, out_t} = s1 - s2; |
ALU_SWP: out_t = {s1[3:0], s1[7:4]}; |
ALU_XOR: out_t = s1 ^ s2; |
ALU_BCF: out_t = s1 & ~mask; |
ALU_BSF: out_t = s1 | mask; |
endcase |
end |
*/ |
|
assign rlf_out = {s1[7:0], c_in}; |
assign rrf_out = {s1[0], c_in, s1[7:1]}; |
|
assign add_sub_sel = (op[3:2]==2'b0); |
|
mux4_8 u2( .sel(op[3:2]), .in0(add_sub_out), .in1(out_next1), .in2(out_next2), .in3(out_next3), .out(out) ); |
mux4_8 u3( .sel(op[1:0]), .in0(s1 & s2), .in1(8'h00), .in2(~s1), .in3(s1 | s2), .out(out_next1) ); |
mux4_8 u4( .sel(op[1:0]), .in0(s1), .in1(s2), .in2(rlf_out[7:0]), .in3(rrf_out[7:0]), .out(out_next2) ); |
mux4_8 u5( .sel(op[1:0]), .in0({s1[3:0], s1[7:4]}), .in1(s1^s2), .in2(s1 & ~mask), .in3(s1 | mask), .out(out_next3) ); |
|
mux2_8 u0( .sel(op[1]), .in0(s2), .in1(8'h01), .out(s2_a) ); |
|
add_sub8_co u1( .sub(op[0]), .opa(s1), .opb(s2_a), .out(add_sub_out), .co(co) ); |
|
// C bit generation |
assign c = add_sub_sel ? co : op[0] ? rrf_out[8] : rlf_out[8]; |
|
// Z Bit generation |
assign z = (out==8'h0); |
|
// DC Bit geberation |
// This section is really bad, but not in the critical path, |
// so I leave it alone for now .... |
assign borrow_dc = s1[3:0] >= s2[3:0]; |
assign tmp_add = s1[3:0] + s2[3:0]; |
assign dc = (op==ALU_SUB) ? borrow_dc : tmp_add[4]; |
|
endmodule |
/trunk/verilog/core/register_file.v
0,0 → 1,90
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Register File //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
|
`timescale 1ns / 10ps |
|
module register_file( clk, |
rf_rd_bnk, rf_rd_addr, rf_rd_data, |
rf_we, rf_wr_bnk, rf_wr_addr, rf_wr_data); |
|
input clk; |
input [1:0] rf_rd_bnk; |
input [4:0] rf_rd_addr; |
output [7:0] rf_rd_data; |
input rf_we; |
input [1:0] rf_wr_bnk; |
input [4:0] rf_wr_addr; |
input [7:0] rf_wr_data; |
|
wire clk; |
wire [7:0] rf_rd_data; |
wire [6:0] rd_addr; |
wire [6:0] wr_addr; |
wire [7:0] rf_rd_data_mem; |
reg [7:0] wr_data_tmp; |
reg rd_wr_addr_equal; |
wire rd_wr_addr_equal_tmp; |
//reg [6:0] rd_adr_r, wr_adr_r; |
|
// Simple Read & Write Address Mapping to memory address |
|
assign rd_addr = rf_rd_addr[4] ? |
{1'b0, rf_rd_bnk, rf_rd_addr[3:0]} : |
{1'b1, 2'b00, 1'b0, rf_rd_addr[2:0]}; |
|
assign wr_addr = rf_wr_addr[4] ? |
{1'b0, rf_wr_bnk, rf_wr_addr[3:0]} : |
{1'b1, 2'b00, 1'b0, rf_wr_addr[2:0]}; |
|
// This logic is to bypass the register file if we are reading and |
// writing (in previous instruction) to the same register |
always @(posedge clk) |
rd_wr_addr_equal <= #1 rd_wr_addr_equal_tmp; |
|
//assign rd_wr_addr_equal_tmp = (rd_addr==wr_addr) & rf_we; |
|
cmp8_eq u0( .eq(rd_wr_addr_equal_tmp), .a({rf_we, rd_addr}), .b({1'b1, wr_addr}) ); |
|
//always @(posedge clk) |
// rd_adr_r <= #1 {rf_rd_bnk, rf_rd_addr}; |
|
//always @(posedge clk) |
// wr_adr_r <= #1 {rf_wr_bnk, rf_wr_addr}; |
|
//cmp8_eq u0( .eq(rd_wr_addr_equal), .a({rf_we, rd_adr_r}), .b({1'b1, wr_adr_r}) ); |
|
//assign rf_rd_data = rd_wr_addr_equal ? wr_data_tmp : rf_rd_data_mem; |
|
mux2_8 u2( .sel(rd_wr_addr_equal), .in1(wr_data_tmp), .in0(rf_rd_data_mem), .out(rf_rd_data) ); |
|
always @(posedge clk) |
wr_data_tmp <= #1 rf_wr_data; |
|
// This is the actual Memory |
ssram_128x8 u1(clk, rd_addr, rf_rd_data_mem, rf_we, wr_addr, rf_wr_data); |
|
|
endmodule |
/trunk/verilog/core/primitives_xilinx.v
0,0 → 1,1054
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Primitives for Xilinx Virtex Famaly //// |
//// (Generated with CoreGen) //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 10ps |
|
// LIB_TAG |
// synopsys translate_off |
// synthesis translate_off |
`include "XilinxCoreLib/C_ADDSUB_V1_0.v" |
`include "XilinxCoreLib/C_MUX_BUS_V1_0.v" |
`include "XilinxCoreLib/C_COMPARE_V1_0.v" |
`include "XilinxCoreLib/C_MUX_BIT_V1_0.v" |
`include "XilinxCoreLib/C_MEM_DP_BLOCK_V1_0.v" |
`include "XilinxCoreLib/C_REG_FD_V1_0.v" |
// synthesis translate_on |
// synopsys translate_on |
// LIB_TAG_END |
|
|
// Mux 4:1 8 bits wide |
module mux4_8(sel, in0, in1, in2, in3, out); |
input [1:0] sel; |
input [7:0] in0, in1, in2, in3; |
output [7:0] out; |
|
// INST_TAG |
xilinx_mux4_8 u0 ( |
.MA0(in0[0]), |
.MA1(in0[1]), |
.MA2(in0[2]), |
.MA3(in0[3]), |
.MA4(in0[4]), |
.MA5(in0[5]), |
.MA6(in0[6]), |
.MA7(in0[7]), |
|
.MB0(in1[0]), |
.MB1(in1[1]), |
.MB2(in1[2]), |
.MB3(in1[3]), |
.MB4(in1[4]), |
.MB5(in1[5]), |
.MB6(in1[6]), |
.MB7(in1[7]), |
|
.MC0(in2[0]), |
.MC1(in2[1]), |
.MC2(in2[2]), |
.MC3(in2[3]), |
.MC4(in2[4]), |
.MC5(in2[5]), |
.MC6(in2[6]), |
.MC7(in2[7]), |
|
.MD0(in3[0]), |
.MD1(in3[1]), |
.MD2(in3[2]), |
.MD3(in3[3]), |
.MD4(in3[4]), |
.MD5(in3[5]), |
.MD6(in3[6]), |
.MD7(in3[7]), |
|
.S0(sel[0]), |
.S1(sel[1]), |
|
.O0(out[0]), |
.O1(out[1]), |
.O2(out[2]), |
.O3(out[3]), |
.O4(out[4]), |
.O5(out[5]), |
.O6(out[6]), |
.O7(out[7]) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_mux4_8 (MA,MB,MC,MD,S,O); // synthesis black_box |
input [7:0] MA; |
input [7:0] MB; |
input [7:0] MC; |
input [7:0] MD; |
input [1:0] S; |
output [7:0] O; |
|
// synopsys translate_off |
// synthesis translate_off |
C_MUX_BUS_V1_0 #( |
"00000000", |
1, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
4, |
0, |
2, |
"00000000", |
0, |
1, |
8) |
inst ( |
.MA(MA), |
.MB(MB), |
.MC(MC), |
.MD(MD), |
.S(S), |
.O(O)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// 8 bit comparator |
module cmp8_eq(a,b,eq); |
input [7:0] a,b; |
output eq; |
|
// INST_TAG |
xilinx_cmp8_eq u0 ( |
.A0(a[0]), |
.A1(a[1]), |
.A2(a[2]), |
.A3(a[3]), |
.A4(a[4]), |
.A5(a[5]), |
.A6(a[6]), |
.A7(a[7]), |
|
.B0(b[0]), |
.B1(b[1]), |
.B2(b[2]), |
.B3(b[3]), |
.B4(b[4]), |
.B5(b[5]), |
.B6(b[6]), |
.B7(b[7]), |
|
.A_EQ_B(eq) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_cmp8_eq (A,B,A_EQ_B); // synthesis black_box |
input [7 : 0] A; |
input [7 : 0] B; |
output A_EQ_B; |
|
// synopsys translate_off |
// synthesis translate_off |
C_COMPARE_V1_0 #( |
"0", |
0, |
"0", |
1, |
1, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
1, |
8) |
inst ( |
.A(A), |
.B(B), |
.A_EQ_B(A_EQ_B)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// MUX 2:1 7 bits wide |
module mux2_7(sel, in0, in1, out); |
input sel; |
input [6:0] in0, in1; |
output [6:0] out; |
|
// INST_TAG |
xilinx_mux2_7 u0 ( |
.MA0(in0[0]), |
.MA1(in0[1]), |
.MA2(in0[2]), |
.MA3(in0[3]), |
.MA4(in0[4]), |
.MA5(in0[5]), |
.MA6(in0[6]), |
|
.MB0(in1[0]), |
.MB1(in1[1]), |
.MB2(in1[2]), |
.MB3(in1[3]), |
.MB4(in1[4]), |
.MB5(in1[5]), |
.MB6(in1[6]), |
|
.S0(sel), |
|
.O0(out[0]), |
.O1(out[1]), |
.O2(out[2]), |
.O3(out[3]), |
.O4(out[4]), |
.O5(out[5]), |
.O6(out[6]) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_mux2_7 (MA,MB,S,O); // synthesis black_box |
input [6 : 0] MA; |
input [6 : 0] MB; |
input [0 : 0] S; |
output [6 : 0] O; |
|
// synopsys translate_off |
// synthesis translate_off |
C_MUX_BUS_V1_0 #( |
"0000000", |
1, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
2, |
0, |
1, |
"0000000", |
0, |
1, |
7) |
inst ( |
.MA(MA), |
.MB(MB), |
.S(S), |
.O(O)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
|
// Mux 8:1 1 bit wide |
module mux8_1( sel, in, out); |
input [2:0] sel; |
input [7:0] in; |
output out; |
|
// INST_TAG |
xilinx_mux8_1 u0 ( |
.M0(in[0]), |
.M1(in[1]), |
.M2(in[2]), |
.M3(in[3]), |
.M4(in[4]), |
.M5(in[5]), |
.M6(in[6]), |
.M7(in[7]), |
|
.S0(sel[0]), |
.S1(sel[1]), |
.S2(sel[2]), |
|
|
.O(out)); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_mux8_1 (M,S,O); // synthesis black_box |
input [7 : 0] M; |
input [2 : 0] S; |
output O; |
|
// synopsys translate_off |
// synthesis translate_off |
C_MUX_BIT_V1_0 #( |
"0", |
1, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
8, |
3, |
"0", |
0, |
1) |
inst ( |
.M(M), |
.S(S), |
.O(O)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// Mux 2:1 8 bits wide |
module mux2_8(sel, in0, in1, out); |
input sel; |
input [7:0] in0, in1; |
output [7:0] out; |
|
// INST_TAG |
xilinx_mux2_8 u0( |
.MA0(in0[0]), |
.MA1(in0[1]), |
.MA2(in0[2]), |
.MA3(in0[3]), |
.MA4(in0[4]), |
.MA5(in0[5]), |
.MA6(in0[6]), |
.MA7(in0[7]), |
|
.MB0(in1[0]), |
.MB1(in1[1]), |
.MB2(in1[2]), |
.MB3(in1[3]), |
.MB4(in1[4]), |
.MB5(in1[5]), |
.MB6(in1[6]), |
.MB7(in1[7]), |
|
.S0(sel), |
|
.O0(out[0]), |
.O1(out[1]), |
.O2(out[2]), |
.O3(out[3]), |
.O4(out[4]), |
.O5(out[5]), |
.O6(out[6]), |
.O7(out[7]) ); |
// INST_TAG_END |
|
endmodule |
|
|
/* |
// MOD_TAG |
module xilinx_mux2_8 (MA, MB, S, O); // synthesis black_box |
input [7 : 0] MA; |
input [7 : 0] MB; |
input [0 : 0] S; |
output [7 : 0] O; |
|
// synopsys translate_off |
// synthesis translate_off |
C_MUX_BUS_V1_0 #( |
"00000000", |
1, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
2, |
0, |
1, |
"00000000", |
0, |
1, |
8) |
inst ( |
.MA(MA), |
.MB(MB), |
.S(S), |
.O(O)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// Mux 8:1 8 bits wide |
module mux8_8(sel, in0, in1, in2, in3, in4, in5, in6, in7, out); |
input [2:0] sel; |
input [7:0] in0, in1, in2, in3, in4, in5, in6, in7; |
output [7:0] out; |
|
// INST_TAG |
xilinx_mux8_8 u0 ( |
.MA0(in0[0]), |
.MA1(in0[1]), |
.MA2(in0[2]), |
.MA3(in0[3]), |
.MA4(in0[4]), |
.MA5(in0[5]), |
.MA6(in0[6]), |
.MA7(in0[7]), |
|
.MB0(in1[0]), |
.MB1(in1[1]), |
.MB2(in1[2]), |
.MB3(in1[3]), |
.MB4(in1[4]), |
.MB5(in1[5]), |
.MB6(in1[6]), |
.MB7(in1[7]), |
|
.MC0(in2[0]), |
.MC1(in2[1]), |
.MC2(in2[2]), |
.MC3(in2[3]), |
.MC4(in2[4]), |
.MC5(in2[5]), |
.MC6(in2[6]), |
.MC7(in2[7]), |
|
.MD0(in3[0]), |
.MD1(in3[1]), |
.MD2(in3[2]), |
.MD3(in3[3]), |
.MD4(in3[4]), |
.MD5(in3[5]), |
.MD6(in3[6]), |
.MD7(in3[7]), |
|
.ME0(in4[0]), |
.ME1(in4[1]), |
.ME2(in4[2]), |
.ME3(in4[3]), |
.ME4(in4[4]), |
.ME5(in4[5]), |
.ME6(in4[6]), |
.ME7(in4[7]), |
|
.MF0(in5[0]), |
.MF1(in5[1]), |
.MF2(in5[2]), |
.MF3(in5[3]), |
.MF4(in5[4]), |
.MF5(in5[5]), |
.MF6(in5[6]), |
.MF7(in5[7]), |
|
.MG0(in6[0]), |
.MG1(in6[1]), |
.MG2(in6[2]), |
.MG3(in6[3]), |
.MG4(in6[4]), |
.MG5(in6[5]), |
.MG6(in6[6]), |
.MG7(in6[7]), |
|
.MH0(in7[0]), |
.MH1(in7[1]), |
.MH2(in7[2]), |
.MH3(in7[3]), |
.MH4(in7[4]), |
.MH5(in7[5]), |
.MH6(in7[6]), |
.MH7(in7[7]), |
|
.S0(sel[0]), |
.S1(sel[1]), |
.S2(sel[2]), |
|
.O0(out[0]), |
.O1(out[1]), |
.O2(out[2]), |
.O3(out[3]), |
.O4(out[4]), |
.O5(out[5]), |
.O6(out[6]), |
.O7(out[7]) ); |
|
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_mux8_8 (MA,MB,MC,MD,ME,MF,MG,MH,S,O); // synthesis black_box |
input [7 : 0] MA; |
input [7 : 0] MB; |
input [7 : 0] MC; |
input [7 : 0] MD; |
input [7 : 0] ME; |
input [7 : 0] MF; |
input [7 : 0] MG; |
input [7 : 0] MH; |
input [2 : 0] S; |
output [7 : 0] O; |
|
// synopsys translate_off |
// synthesis translate_off |
C_MUX_BUS_V1_0 #( |
"00000000", |
1, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
8, |
0, |
3, |
"00000000", |
0, |
1, |
8) |
inst ( |
.MA(MA), |
.MB(MB), |
.MC(MC), |
.MD(MD), |
.ME(ME), |
.MF(MF), |
.MG(MG), |
.MH(MH), |
.S(S), |
.O(O)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// Mux 2:1 11 bits wide |
module mux2_11(sel, in0, in1, out); |
input sel; |
input [10:0] in0, in1; |
output [10:0] out; |
|
// INST_TAG |
xilinx_mux2_11 u0 ( |
.MA0(in0[0]), |
.MA1(in0[1]), |
.MA2(in0[2]), |
.MA3(in0[3]), |
.MA4(in0[4]), |
.MA5(in0[5]), |
.MA6(in0[6]), |
.MA7(in0[7]), |
.MA8(in0[8]), |
.MA9(in0[9]), |
.MA10(in0[10]), |
|
.MB0(in1[0]), |
.MB1(in1[1]), |
.MB2(in1[2]), |
.MB3(in1[3]), |
.MB4(in1[4]), |
.MB5(in1[5]), |
.MB6(in1[6]), |
.MB7(in1[7]), |
.MB8(in1[8]), |
.MB9(in1[9]), |
.MB10(in1[10]), |
|
.S0(sel), |
|
.O0(out[0]), |
.O1(out[1]), |
.O2(out[2]), |
.O3(out[3]), |
.O4(out[4]), |
.O5(out[5]), |
.O6(out[6]), |
.O7(out[7]), |
.O8(out[8]), |
.O9(out[9]), |
.O10(out[10]) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_mux2_11 (MA,MB,S,O); // synthesis black_box |
input [10 : 0] MA; |
input [10 : 0] MB; |
input [0 : 0] S; |
output [10 : 0] O; |
|
// synopsys translate_off |
// synthesis translate_off |
C_MUX_BUS_V1_0 #( |
"00000000000", |
1, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
2, |
0, |
1, |
"00000000000", |
0, |
1, |
11) |
inst ( |
.MA(MA), |
.MB(MB), |
.S(S), |
.O(O)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
|
// 8bit Add/Sub with carry/borrow out |
module add_sub8_co(sub, opa, opb, out, co); |
input sub; |
input [7:0] opa, opb; |
output [7:0] out; |
output co; |
|
wire add; |
assign add = ~sub; |
|
// INST_TAG |
xilinx_add_sub8_co u0 ( |
.A0(opa[0]), |
.A1(opa[1]), |
.A2(opa[2]), |
.A3(opa[3]), |
.A4(opa[4]), |
.A5(opa[5]), |
.A6(opa[6]), |
.A7(opa[7]), |
|
.B0(opb[0]), |
.B1(opb[1]), |
.B2(opb[2]), |
.B3(opb[3]), |
.B4(opb[4]), |
.B5(opb[5]), |
.B6(opb[6]), |
.B7(opb[7]), |
|
.C_OUT(co), |
.ADD(add), |
|
.S0(out[0]), |
.S1(out[1]), |
.S2(out[2]), |
.S3(out[3]), |
.S4(out[4]), |
.S5(out[5]), |
.S6(out[6]), |
.S7(out[7]) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_add_sub8_co (A,B,C_OUT,ADD,S); // synthesis black_box |
input [7 : 0] A; |
input [7 : 0] B; |
output C_OUT; |
input ADD; |
output [7 : 0] S; |
|
// synopsys translate_off |
// synthesis translate_off |
C_ADDSUB_V1_0 #( |
2, |
"0000", |
1, |
8, |
0, |
0, |
0, |
1, |
"0", |
8, |
1, |
0, |
1, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
7, |
0, |
8, |
1, |
"0", |
0, |
1) |
inst ( |
.A(A), |
.B(B), |
.C_OUT(C_OUT), |
.ADD(ADD), |
.S(S)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// 11 bit incrementer |
module inc11(in, out); |
input [10:0] in; |
output [10:0] out; |
|
// INST_TAG |
xilinx_inc11 u0 ( |
.A0(in[0]), |
.A1(in[1]), |
.A2(in[2]), |
.A3(in[3]), |
.A4(in[4]), |
.A5(in[5]), |
.A6(in[6]), |
.A7(in[7]), |
.A8(in[8]), |
.A9(in[9]), |
.A10(in[10]), |
|
.S0(out[0]), |
.S1(out[1]), |
.S2(out[2]), |
.S3(out[3]), |
.S4(out[4]), |
.S5(out[5]), |
.S6(out[6]), |
.S7(out[7]), |
.S8(out[8]), |
.S9(out[9]), |
.S10(out[10]) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_inc11 (A,S); // synthesis black_box |
input [10 : 0] A; |
output [10 : 0] S; |
|
// synopsys translate_off |
// synthesis translate_off |
C_ADDSUB_V1_0 #( |
0, |
"0000", |
1, |
11, |
0, |
0, |
1, |
1, |
"0001", |
11, |
1, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
10, |
0, |
11, |
1, |
"0", |
0, |
1) |
inst ( |
.A(A), |
.S(S)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
// 8 bit incrementer |
module inc8(in, out); |
input [7:0] in; |
output [7:0] out; |
|
// INST_TAG |
xilinx_inc8 u0 ( |
.A0(in[0]), |
.A1(in[1]), |
.A2(in[2]), |
.A3(in[3]), |
.A4(in[4]), |
.A5(in[5]), |
.A6(in[6]), |
.A7(in[7]), |
|
.S0(out[0]), |
.S1(out[1]), |
.S2(out[2]), |
.S3(out[3]), |
.S4(out[4]), |
.S5(out[5]), |
.S6(out[6]), |
.S7(out[7]) ); |
// INST_TAG_END |
|
endmodule |
|
/* |
// MOD_TAG |
module xilinx_inc8 (A,S); // synthesis black_box |
input [7 : 0] A; |
output [7 : 0] S; |
|
// synopsys translate_off |
// synthesis translate_off |
C_ADDSUB_V1_0 #( |
0, |
"0000", |
1, |
8, |
0, |
0, |
1, |
1, |
"0001", |
8, |
1, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
1, |
0, |
0, |
0, |
7, |
0, |
8, |
1, |
"0", |
0, |
1) |
inst ( |
.A(A), |
.S(S)); |
// synthesis translate_on |
// synopsys translate_on |
endmodule |
// MOD_TAG_END |
*/ |
|
|
// A Basic Synchrounous FIFO (4 entries deep) |
module sfifo4x11(clk, push, din, pop, dout); |
input clk; |
input push; |
input [10:0] din; |
input pop; |
output [10:0] dout; |
|
reg [10:0] stack1, stack2, stack3, stack4; |
|
assign dout = stack1; |
|
always @(posedge clk) |
begin |
if(push) // PUSH stack |
begin |
stack4 <= #1 stack3; |
stack3 <= #1 stack2; |
stack2 <= #1 stack1; |
stack1 <= #1 din; |
end |
if(pop) // POP stack |
begin |
stack1 <= #1 stack2; |
stack2 <= #1 stack3; |
stack3 <= #1 stack4; |
end |
end |
|
endmodule |
|
|
// Synchrounous SRAM |
// 128 bytes by 8 bits |
// 1 read port, 1 write port |
// FOR XILINX VERTEX SERIES |
module ssram_128x8(clk, rd_addr, rd_data, we, wr_addr, wr_data); |
input clk; |
input [6:0] rd_addr; |
output [7:0] rd_data; |
input we; |
input [6:0] wr_addr; |
input [7:0] wr_data; |
|
wire [7:0] tmp; |
|
|
// Alternatively RAMs can be instantiated directly |
RAMB4_S8_S8 u0( |
.DOA( rd_data ), |
.ADDRA( {2'b0, rd_addr} ), |
.DIA( 8'h00 ), |
.ENA( 1'b1 ), |
.CLKA( clk ), |
.WEA( 1'b0 ), |
.RSTA( 1'b0 ), |
.DOB( tmp ), |
.ADDRB( {2'b0, wr_addr} ), |
.DIB( wr_data ), |
.ENB( 1'b1 ), |
.CLKB( clk ), |
.WEB( we ), |
.RSTB( 1'b0 ) ); |
|
|
endmodule |
|
|
|
// This block is the global Set/Rest for Xilinx VIrtex Serries |
// Connect it up as described in Xilinx documentation |
// Leave it out for Non Xilinx implementations |
module glbl(rst); |
input rst; |
|
wire GSR; |
|
assign GSR = rst; |
|
endmodule |
|
|
/trunk/verilog/core/presclr_wdt.v
0,0 → 1,118
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Prescaler and Wachdog Counter //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
`timescale 1ns / 10ps |
|
// Prescaler and Wachdog Counter |
module presclr_wdt(clk, rst, tcki, option, tmr0_we, tmr0_cnt_en, wdt_en, wdt_clr, wdt_to); |
input clk; |
input rst; |
input tcki; |
input [5:0] option; |
input tmr0_we; |
output tmr0_cnt_en; |
input wdt_en, wdt_clr; |
output wdt_to; |
|
|
reg [7:0] prescaler; |
reg [7:0] wdt; |
|
reg tmr0_cnt_en; |
reg tcki_r; |
reg wdt_to; |
|
wire tose; |
wire tosc; |
wire psa; |
wire [2:0] ps; |
wire tcki_a, tcki_b; |
wire presclr_ce; |
wire prsclr_clr; |
wire wdt_to_direct; |
reg presclr_out, presclr_out_r1; |
wire presclr_out_next; |
wire [7:0] presclr_plus_1, wdt_plus_1; |
wire [7:0] prescaler_next, prescaler_next1; |
wire [7:0] wdt_next, wdt_next1; |
|
// Inputs select |
assign ps = option[2:0]; |
assign psa = option[3]; |
assign tose = option[4]; |
assign tosc = option[5]; |
|
always @(posedge clk) |
tcki_r <= #1 tcki; |
|
assign tcki_a = tose ^ tcki_r; |
assign tcki_b = tosc ? tcki_a : 1'b1; |
assign presclr_ce = psa ? wdt_to_direct : tcki_b; |
|
always @(posedge clk) |
tmr0_cnt_en <= #1 psa ? tcki_b : presclr_out; |
|
|
// Prescaler |
assign prsclr_clr = psa ? wdt_clr : tmr0_we; |
|
always @(posedge clk) |
//if(rst | prsclr_clr) prescaler <= #1 8'h00; |
//else |
//if(presclr_ce) prescaler <= #1 presclr_plus_1; |
prescaler <= #1 prescaler_next; |
|
mux2_8 u3( .sel(rst | prsclr_clr), .in1(8'h00), .in0(prescaler_next1), .out(prescaler_next) ); |
mux2_8 u4( .sel(presclr_ce), .in1(presclr_plus_1), .in0(prescaler), .out(prescaler_next1) ); |
|
|
mux8_1 u2( .sel(ps), .in(prescaler), .out(presclr_out_next) ); |
|
always @(posedge clk) |
presclr_out_r1 <= #1 presclr_out_next; |
|
always @(posedge clk) // Edge detector for prescaler output |
presclr_out <= #1 presclr_out_next & ~presclr_out_r1 & ~prsclr_clr; |
|
inc8 u0( .in(prescaler), .out(presclr_plus_1)); |
|
// Wachdog timer |
always @(posedge clk) |
wdt_to <= #1 psa ? presclr_out : wdt_to_direct; |
|
always @(posedge clk) |
//if(rst | wdt_clr) wdt <= #1 8'h00; |
//else |
//if(wdt_en) wdt <= #1 wdt_plus_1; |
wdt <= #1 wdt_next; |
|
mux2_8 u5( .sel(rst | wdt_clr), .in1(8'h00), .in0(wdt_next1), .out(wdt_next) ); |
mux2_8 u6( .sel(wdt_en), .in1(wdt_plus_1), .in0(wdt), .out(wdt_next1) ); |
|
assign wdt_to_direct = (wdt == 8'hff); |
|
inc8 u1( .in(wdt), .out(wdt_plus_1) ); |
|
endmodule |
/trunk/verilog/core/risc_core.v
0,0 → 1,797
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Mini-Risc Core //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
|
`timescale 1ns / 10ps |
|
module mrisc( |
clk, |
rst_in, |
|
inst_addr, |
inst_data, |
|
portain, |
portbin, |
portcin, |
|
portaout, |
portbout, |
portcout, |
|
trisa, |
trisb, |
trisc, |
|
tcki, |
wdt_en ); |
|
// Basic Core I/O. |
input clk; |
input rst_in; |
|
// Program memory interface |
output [10:0] inst_addr; |
input [11:0] inst_data; |
|
// Basic I/O Ports |
input [7:0] portain; |
input [7:0] portbin; |
input [7:0] portcin; |
|
output [7:0] portaout; |
output [7:0] portbout; |
output [7:0] portcout; |
|
output [7:0] trisa; |
output [7:0] trisb; |
output [7:0] trisc; |
|
input tcki; |
input wdt_en; |
|
// This should be set to the ROM location where our restart vector is. |
// As set here, we have 512 words of program space. |
parameter PC_RST_VECTOR = 11'h000, // Should be: 11'h7FF, |
STAT_RST_VALUE = 8'h18, |
OPT_RST_VALUE = 8'h3f, |
FSR_RST_VALUE = 7'h0, |
TRIS_RST_VALUE = 8'hff; |
|
parameter ALU_ADD = 4'h0, |
ALU_SUB = 4'h1, |
ALU_INC = 4'h2, |
ALU_DEC = 4'h3, |
|
ALU_AND = 4'h4, |
ALU_CLR = 4'h5, |
ALU_NOT = 4'h6, |
ALU_IOR = 4'h7, |
ALU_MOV = 4'h8, |
ALU_MOVW = 4'h9, |
ALU_RLF = 4'ha, |
ALU_RRF = 4'hb, |
ALU_SWP = 4'hc, |
ALU_XOR = 4'hd, |
ALU_BCF = 4'he, |
ALU_BSF = 4'hf; |
|
parameter // Byte Oriented RF Operations |
I_ADDWF = 12'b0001_11??_????, |
I_ANDWF = 12'b0001_01??_????, |
I_CLRF = 12'b0000_011?_????, |
I_CLRW = 12'b0000_0100_0000, |
I_COMF = 12'b0010_01??_????, |
I_DEC = 12'b0000_11??_????, |
I_DECFSZ = 12'b0010_11??_????, |
I_INCF = 12'b0010_10??_????, |
I_INCFSZ = 12'b0011_11??_????, |
I_IORWF = 12'b0001_00??_????, |
I_MOV = 12'b0010_00??_????, |
I_MOVWF = 12'b0000_001?_????, |
I_NOP = 12'b0000_0000_0000, |
I_RLF = 12'b0011_01??_????, |
I_RRF = 12'b0011_00??_????, |
I_SUBWF = 12'b0000_10??_????, |
I_SWAPF = 12'b0011_10??_????, |
I_XORWF = 12'b0001_10??_????, |
|
// Bit Oriented RF Operations |
I_BCF = 12'b0100_????_????, |
I_BSF = 12'b0101_????_????, |
I_BTFSC = 12'b0110_????_????, |
I_BTFSS = 12'b0111_????_????, |
|
// Literal & Controll Operations |
I_ANDLW = 12'b1110_????_????, |
I_CALL = 12'b1001_????_????, |
I_CLRWDT = 12'b0000_0000_0100, |
I_GOTO = 12'b101?_????_????, |
I_IORLW = 12'b1101_????_????, |
I_MOVLW = 12'b1100_????_????, |
I_OPTION = 12'b0000_0000_0010, |
I_RETLW = 12'b1000_????_????, |
I_SLEEP = 12'b0000_0000_0011, |
I_TRIS = 12'b0000_0000_0???, |
I_XORLW = 12'b1111_????_????; |
|
parameter // sfr register address encodings |
INDF_ADDR = 3'h0, |
TMR0_ADDR = 3'h1, |
PCL_ADDR = 3'h2, |
STAT_ADDR = 3'h3, |
FSR_ADDR = 3'h4, |
PORTA_ADDR = 3'h5, |
PORTB_ADDR = 3'h6, |
PORTC_ADDR = 3'h7; |
|
parameter // Source 1 Select |
K_SEL = 2'b10, |
SFR_SEL = 2'b00, |
RF_SEL = 2'b01; |
|
parameter // STATUS Register status bits we |
STAT_WR_C = 3'b001, |
STAT_WR_DC = 3'b010, |
STAT_WR_Z = 3'b100; |
|
|
// Instruction Register |
reg rst; |
reg [11:0] instr_0, instr_1; |
reg rst_r1, rst_r2; |
wire valid; |
reg valid_1; |
|
reg [7:0] mask; |
reg [7:0] sfr_rd_data; |
reg [3:0] alu_op; |
reg src1_sel; |
reg [1:0] src1_sel_; |
|
wire [7:0] dout; // ALU output |
wire [7:0] src1; // ALU Source 1 |
|
reg [2:0] stat_bwe; // status bits we |
wire c_out, dc_out, z_out; |
|
reg pc_skz, pc_skz_; |
reg pc_bset, pc_bset_; |
reg pc_bclr, pc_bclr_; |
reg pc_call, pc_call_; |
reg pc_goto, pc_goto_; |
reg pc_retlw, pc_retlw_; |
|
wire invalidate_1; |
wire invalidate_0_; |
reg invalidate_0; |
|
// stage 1 dst decode |
reg w_we_; |
reg rf_we_; |
reg sfr_we_; |
reg tris_we_; |
|
// stage 2 dst decode |
reg w_we; |
wire rf_we; |
reg rf_we1, rf_we2, rf_we3; |
|
reg opt_we; |
reg trisa_we; |
reg trisb_we; |
reg trisc_we; |
|
wire indf_we_; |
reg tmr0_we; |
wire pc_we_; |
reg pc_we; |
reg stat_we; |
reg fsr_we; |
reg porta_we; |
reg portb_we; |
reg portc_we; |
|
wire bit_sel; |
wire [7:0] tmr0_next, tmr0_next1, tmr0_plus_1; |
wire tmr0_cnt_en; |
reg wdt_clr; |
wire wdt_to; |
wire wdt_en; |
wire tcki; |
|
wire [7:0] sfr_rd_data_tmp1, sfr_rd_data_tmp2, sfr_rd_data_tmp3; |
|
// Register File Connections |
wire [1:0] rf_rd_bnk, rf_wr_bnk; |
wire [4:0] rf_rd_addr, rf_wr_addr; |
wire [7:0] rf_rd_data, rf_wr_data; |
|
// Program Counter |
reg [10:0] inst_addr; |
reg [10:0] pc; |
wire [10:0] pc_next; |
wire [10:0] pc_plus_1; |
wire [10:0] stack_out; |
reg [10:0] pc_r, pc_r2; |
wire [10:0] pc_next1, pc_next2, pc_next3; |
|
// W Register |
reg [7:0] w; // Working Register |
reg [7:0] status; // Status Register |
wire [7:0] status_next; |
reg [6:0] fsr; // fsr register ( for indirect addressing) |
wire [6:0] fsr_next; |
reg [7:0] tmr0; // Timer 0 |
reg [5:0] option; // Option Register |
|
// Tristate Control registers. |
reg [7:0] trisa; |
reg [7:0] trisb; |
reg [7:0] trisc; |
|
// I/O Port registers |
reg [7:0] porta_r; // PORTA input register |
reg [7:0] portb_r; // PORTB input register |
reg [7:0] portc_r; // PORTC input register |
reg [7:0] portaout; // PORTA output register |
reg [7:0] portbout; // PORTB output register |
reg [7:0] portcout; // PORTC output register |
|
//////////////////////////////////////////////////////////////////////// |
// External Reset is Synchrounous to clock |
always @(posedge clk) |
rst <= #1 rst_in; |
|
//////////////////////////////////////////////////////////////////////// |
// Synchrounous Register File |
register_file u0( .clk(clk), .rf_rd_bnk(rf_rd_bnk), .rf_rd_addr(rf_rd_addr), .rf_rd_data(rf_rd_data), |
.rf_we(rf_we), .rf_wr_bnk(rf_wr_bnk), .rf_wr_addr(rf_wr_addr), .rf_wr_data(rf_wr_data) ); |
|
//////////////////////////////////////////////////////////////////////// |
// Always Fetch Next Instruction |
always @(posedge clk) |
instr_0 <= #1 inst_data; |
|
//////////////////////////////////////////////////////////////////////// |
// Instr Decode & Read Logic |
|
always @(posedge clk) |
begin |
rst_r1 <= #1 rst | wdt_to; |
rst_r2 <= #1 rst | rst_r1 | wdt_to; |
end |
|
assign valid = ~rst_r2 & ~invalidate_1; |
always @(posedge clk) |
valid_1 <= #1 valid; |
|
always @(posedge clk) // Basic Decode extracted directly from the instruction |
begin |
instr_1 <= #1 instr_0; |
// Mask for bit modification instructions |
case(instr_0[7:5]) // synopsys full_case parallel_case |
0: mask <= #1 8'h01; |
1: mask <= #1 8'h02; |
2: mask <= #1 8'h04; |
3: mask <= #1 8'h08; |
4: mask <= #1 8'h10; |
5: mask <= #1 8'h20; |
6: mask <= #1 8'h40; |
7: mask <= #1 8'h80; |
endcase |
end |
|
always @(posedge clk) |
pc_r <= #1 pc; // Previous version of PC to accomodate for pipeline |
|
/* |
always @(posedge clk) // SFR Read Operands |
if(src1_sel_[1]) sfr_rd_data <= #1 instr_0[7:0]; |
else |
case(instr_0[2:0]) // synopsys full_case parallel_case |
1: sfr_rd_data <= #1 tmr0_next; |
2: sfr_rd_data <= #1 pc_r[7:0]; |
3: sfr_rd_data <= #1 status_next; |
4: sfr_rd_data <= #1 {1'b1, fsr_next}; |
5: sfr_rd_data <= #1 porta_r; |
6: sfr_rd_data <= #1 portb_r; |
7: sfr_rd_data <= #1 portc_r; |
endcase |
*/ |
|
always @(posedge clk) |
sfr_rd_data <= #1 sfr_rd_data_tmp1; |
|
|
reg [3:0] sfr_sel; |
wire [3:0] sfr_sel_src; |
|
assign sfr_sel_src = {src1_sel_[1],instr_0[2:0]}; |
|
always @(sfr_sel_src) |
casex(sfr_sel_src) // synopsys full_case parallel_case |
4'b1_???: sfr_sel = 4'b01_11; |
4'b0_001: sfr_sel = 4'bxx_00; |
4'b0_010: sfr_sel = 4'b00_11; |
4'b0_011: sfr_sel = 4'bxx_01; |
4'b0_100: sfr_sel = 4'bxx_10; |
4'b0_101: sfr_sel = 4'b10_11; |
4'b0_11?: sfr_sel = 4'b11_11; |
endcase |
|
|
mux4_8 u1( .sel(sfr_sel[1:0]), .out(sfr_rd_data_tmp1), |
.in0(tmr0_next), .in1(status_next), |
.in2({1'b1, fsr_next}), .in3(sfr_rd_data_tmp2) ); |
|
mux4_8 u2( .sel(sfr_sel[3:2]), .out(sfr_rd_data_tmp2), |
.in0(pc_r[7:0]), .in1(instr_0[7:0]), |
.in2(porta_r), .in3(sfr_rd_data_tmp3) ); |
|
mux2_8 u2b( .sel(instr_0[0]), .out(sfr_rd_data_tmp3), |
.in0(portb_r), .in1(portc_r) ); |
|
|
// Register File Read Port |
assign rf_rd_bnk = fsr_next[6:5]; |
assign rf_rd_addr = (instr_0[4:0]==0) ? fsr_next[4:0] : instr_0[4:0]; |
|
|
// ALU OP |
always @(posedge clk) |
casex(instr_0) // synopsys full_case |
// Byte Oriented RF Operations |
I_ADDWF: alu_op <= #1 ALU_ADD; // ADDWF |
I_ANDWF: alu_op <= #1 ALU_AND; // ANDWF |
I_CLRF: alu_op <= #1 ALU_CLR; // CLRF |
I_CLRW: alu_op <= #1 ALU_CLR; // CLRW |
I_COMF: alu_op <= #1 ALU_NOT; // COMF |
I_DEC: alu_op <= #1 ALU_DEC; // DEC |
I_DECFSZ: alu_op <= #1 ALU_DEC; // DECFSZ |
I_INCF: alu_op <= #1 ALU_INC; // INCF |
I_INCFSZ: alu_op <= #1 ALU_INC; // INCFSZ |
I_IORWF: alu_op <= #1 ALU_IOR; // IORWF |
I_MOV: alu_op <= #1 ALU_MOV; // MOV |
I_MOVWF: alu_op <= #1 ALU_MOVW; // MOVWF |
I_RLF: alu_op <= #1 ALU_RLF; // RLF |
I_RRF: alu_op <= #1 ALU_RRF; // RRF |
I_SUBWF: alu_op <= #1 ALU_SUB; // SUBWF |
I_SWAPF: alu_op <= #1 ALU_SWP; // SWAPF |
I_XORWF: alu_op <= #1 ALU_XOR; // XORWF |
// Bit Oriented RF Operations |
I_BCF: alu_op <= #1 ALU_BCF; // BCF |
I_BSF: alu_op <= #1 ALU_BSF; // BSF |
// Literal & Controll Operations |
I_ANDLW: alu_op <= #1 ALU_AND; // ANDLW |
I_IORLW: alu_op <= #1 ALU_IOR; // IORLW |
I_MOVLW: alu_op <= #1 ALU_MOV; // MOWLW |
I_RETLW: alu_op <= #1 ALU_MOV; // RETLW |
I_XORLW: alu_op <= #1 ALU_XOR; // XORLW |
endcase |
|
|
|
// Source Select |
// This CPU source 1 can be one of: rf (or sfr) or k, |
// second source (if any) is always w |
always @(instr_0) |
casex(instr_0) // synopsys full_case parallel_case |
I_ANDLW: src1_sel_ = K_SEL; |
I_CALL: src1_sel_ = K_SEL; |
I_GOTO: src1_sel_ = K_SEL; |
I_IORLW: src1_sel_ = K_SEL; |
I_MOVLW: src1_sel_ = K_SEL; |
I_RETLW: src1_sel_ = K_SEL; |
I_XORLW: src1_sel_ = K_SEL; |
default: src1_sel_ = (instr_0[4:3]==2'h0 & instr_0[2:0] != 0) ? SFR_SEL : RF_SEL; |
endcase |
|
always @(posedge clk) |
src1_sel <= #1 src1_sel_[0]; |
|
// Destination Select |
// Destination can be one of: rf, w, option, tris OR one of sfr registers: |
// indf, tmr0, pc, status, fsr, porta, portb, portc, option, trisa, trisb, trisc |
// Stage 1 |
// select w, pc, rf or sfr |
reg w_we1, w_we1_; |
|
always @(instr_0) |
begin |
casex(instr_0) // synopsys full_case parallel_case |
I_ADDWF, I_ANDWF, I_COMF, I_DEC, |
I_DECFSZ, I_INCF, I_INCFSZ, I_IORWF, |
I_MOV, I_RLF, I_RRF, I_SUBWF, |
I_SWAPF, I_XORWF: // w or f |
w_we1_ = 1; |
default: w_we1_ = 0; |
endcase |
end |
|
always @(instr_0) |
begin |
w_we_ = 0; |
rf_we_ = 0; |
sfr_we_ = 0; |
tris_we_= 0; |
casex(instr_0) // synopsys full_case parallel_case |
|
I_ADDWF, I_ANDWF, I_COMF, I_DEC, |
I_DECFSZ, I_INCF, I_INCFSZ, I_IORWF, |
I_MOV, I_RLF, I_RRF, I_SUBWF, |
I_SWAPF, I_XORWF: // w or f |
begin |
rf_we_ = instr_0[5] & (instr_0[4] | instr_0[3]); |
sfr_we_ = instr_0[5] & ~instr_0[4] & ~instr_0[3]; |
end |
|
I_MOVWF, I_CLRF, I_BCF, I_BSF: // only f |
begin |
rf_we_ = instr_0[4] | instr_0[3]; |
sfr_we_ = ~instr_0[4] & ~instr_0[3]; |
end |
|
I_CLRW, I_IORLW, I_MOVLW, |
I_ANDLW, I_RETLW, I_XORLW: w_we_ = 1; // only w |
I_TRIS: tris_we_ = 1; // trisa or trisb or trisc |
|
endcase |
end |
|
assign indf_we_ = sfr_we_ & (instr_0[2:0] == INDF_ADDR); |
assign pc_we_ = sfr_we_ & (instr_0[2:0] == PCL_ADDR); |
|
// Stage 2 destination encoder |
// write enable outputs are registered now |
always @(posedge clk) |
w_we <= #1 w_we_; // working register write 0 enable |
|
always @(posedge clk) |
w_we1 <= #1 w_we1_; // working register write 1 enable |
|
|
// Register File Write Enable is composed of thee conditions: 1) direct register writing (0x10-0x1f); |
// 2) Direct Global Register writing (0x08-0x0f), and 3) Indirect Register File Writing |
// The logic has been partitioned and balanced between the decode and execute stage ... |
/* |
assign rf_we = (valid_1 & rf_we1) | (valid_1 & rf_we2 & rf_we3);// register file write enable Composite |
|
always @(posedge clk) |
rf_we1 <= #1 rf_we_; // register file write enable 1 |
|
always @(posedge clk) |
rf_we2 <= #1 fsr_next[4] | fsr_next[3]; // register file write enable 2 |
|
always @(posedge clk) |
rf_we3 <= #1 indf_we_; // register file write enable 3 |
*/ |
|
assign rf_we = rf_we1 | (rf_we2 & rf_we3);// register file write enable Composite |
|
always @(posedge clk) |
rf_we1 <= #1 valid & rf_we_; // register file write enable 1 |
|
always @(posedge clk) |
rf_we2 <= #1 valid & (fsr_next[4] | fsr_next[3]); // register file write enable 2 |
|
always @(posedge clk) |
rf_we3 <= #1 indf_we_; // register file write enable 3 |
|
|
|
|
always @(posedge clk) |
wdt_clr <= #1 instr_0[11:0] == I_CLRWDT; |
|
|
always @(posedge clk) |
opt_we <= #1 instr_0[11:0] == I_OPTION; |
|
|
always @(posedge clk) |
trisa_we <= #1 tris_we_ & (instr_0[2:0] == PORTA_ADDR); |
|
always @(posedge clk) |
trisb_we <= #1 tris_we_ & (instr_0[2:0] == PORTB_ADDR); |
|
always @(posedge clk) |
trisc_we <= #1 tris_we_ & (instr_0[2:0] == PORTC_ADDR); |
|
always @(posedge clk) |
begin |
// SFR registers |
tmr0_we <= #1 sfr_we_ & (instr_0[2:0] == TMR0_ADDR); |
pc_we <= #1 valid & pc_we_; |
stat_we <= #1 valid & sfr_we_ & (instr_0[2:0] == STAT_ADDR); |
fsr_we <= #1 valid & sfr_we_ & (instr_0[2:0] == FSR_ADDR); |
porta_we <= #1 sfr_we_ & (instr_0[2:0] == PORTA_ADDR); |
portb_we <= #1 sfr_we_ & (instr_0[2:0] == PORTB_ADDR); |
portc_we <= #1 sfr_we_ & (instr_0[2:0] == PORTC_ADDR); |
end |
|
|
// Instructions that directly modify PC |
always @(instr_0) |
begin |
pc_skz_ = 0; |
pc_bset_ = 0; |
pc_bclr_ = 0; |
pc_call_ = 0; |
pc_goto_ = 0; |
pc_retlw_ = 0; |
casex(instr_0) // synopsys full_case parallel_case |
// Byte Oriented RF Operations |
I_DECFSZ, |
I_INCFSZ: pc_skz_ = 1; |
// Bit Oriented RF Operations |
I_BTFSS: pc_bset_ = 1; |
I_BTFSC: pc_bclr_ = 1; |
// Literal & Controll Operations |
I_CALL: pc_call_ = 1; |
I_GOTO: pc_goto_ = 1; |
I_RETLW: pc_retlw_ = 1; |
endcase |
end |
|
|
always @(posedge clk) |
begin |
pc_skz <= #1 valid & pc_skz_; |
pc_bset <= #1 valid & pc_bset_; |
pc_bclr <= #1 valid & pc_bclr_; |
pc_call <= #1 valid & pc_call_; |
pc_goto <= #1 valid & pc_goto_; |
pc_retlw <= #1 valid & pc_retlw_; |
end |
|
assign invalidate_0_ = (pc_call_ | pc_goto_ | pc_retlw_ | pc_we_); |
|
always @(posedge clk) |
invalidate_0 <= #1 invalidate_0_; |
|
// Status bits WE |
always @(posedge clk) |
begin |
stat_bwe <= #1 0; |
if(valid) |
casex(instr_0) // synopsys full_case parallel_case |
// Byte Oriented RF Operations |
I_ADDWF: stat_bwe <= #1 STAT_WR_C | STAT_WR_DC | STAT_WR_Z; |
I_ANDWF: stat_bwe <= #1 STAT_WR_Z; |
I_CLRF: stat_bwe <= #1 STAT_WR_Z; |
I_CLRW: stat_bwe <= #1 STAT_WR_Z; |
I_COMF: stat_bwe <= #1 STAT_WR_Z; |
I_DEC: stat_bwe <= #1 STAT_WR_Z; |
I_INCF: stat_bwe <= #1 STAT_WR_Z; |
I_IORWF: stat_bwe <= #1 STAT_WR_Z; |
I_MOV: stat_bwe <= #1 STAT_WR_Z; |
I_RLF: stat_bwe <= #1 STAT_WR_C; |
I_RRF: stat_bwe <= #1 STAT_WR_C; |
I_SUBWF: stat_bwe <= #1 STAT_WR_C | STAT_WR_DC | STAT_WR_Z; |
I_XORWF: stat_bwe <= #1 STAT_WR_Z; |
// Literal & Controll Operations |
I_ANDLW: stat_bwe <= #1 STAT_WR_Z; |
//I_CLRWDT: // Modifies TO & PD *** FIX ME *** |
I_IORLW: stat_bwe <= #1 STAT_WR_Z; |
//I_SLEEP: // Modifies TO & PD *** FIX ME *** |
I_XORLW: stat_bwe <= #1 STAT_WR_Z; |
endcase |
end |
|
//////////////////////////////////////////////////////////////////////// |
// Wr & Execute Logic (including PC) |
// Second Pipeline Stage |
//////////////////////////////////////////////////////////////////////// |
|
// Source OP Sel |
//assign src1 = src1_sel ? rf_rd_data : sfr_rd_data; |
mux2_8 u3( .sel(src1_sel), .in0(sfr_rd_data), .in1(rf_rd_data), .out(src1) ); |
|
alu u4( .s1(src1), .s2(w), .mask(mask), .out(dout), |
.op(alu_op), .c_in(status[0]), .c(c_out), .dc(dc_out), .z(z_out) ); |
|
// Register file connections |
assign rf_wr_bnk = fsr[6:5]; |
assign rf_wr_addr = (instr_1[4:0]==0) ? fsr[4:0] : instr_1[4:0]; |
assign rf_wr_data = dout; |
|
wire [7:0] status_next2; |
|
// Deal with all special registers (SFR) writes |
/* |
always @(rst or status or stat_we or stat_bwe or dout or c_out or dc_out or z_out) |
if(rst) status_next = STAT_RST_VALUE; |
else |
begin |
status_next = status; // Default Keep Value |
if(stat_we) status_next = dout | 8'h18; |
else |
begin |
if(stat_bwe[0]) status_next[0] = c_out; |
if(stat_bwe[1]) status_next[1] = dc_out; |
if(stat_bwe[2]) status_next[2] = z_out; |
end |
end |
*/ |
|
assign status_next2[0] = stat_bwe[0] ? c_out : status[0]; |
assign status_next2[1] = stat_bwe[1] ? dc_out : status[1]; |
assign status_next2[2] = stat_bwe[2] ? z_out : status[2]; |
|
mux2_8 u21( .sel(stat_we), .in1( {dout | 8'h18} ), .in0( {status[7:3],status_next2[2:0]} ), .out(status_next) ); |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) status <= #1 STAT_RST_VALUE; |
else status <= #1 status_next; |
|
//assign fsr_next = fsr_we ? dout[6:0] : fsr; |
|
mux2_7 u31( .sel(fsr_we), .in1(dout[6:0]), .in0(fsr), .out(fsr_next) ); |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) fsr <= #1 FSR_RST_VALUE; |
else fsr <= #1 fsr_next; |
|
always @(posedge clk) |
if(valid_1 & (w_we | (w_we1 & ~instr_1[5])) ) w <= #1 dout; |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) trisa <= #1 TRIS_RST_VALUE; |
else |
if(trisa_we & valid_1) trisa <= #1 w; |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) trisb <= #1 TRIS_RST_VALUE; |
else |
if(trisb_we & valid_1) trisb <= #1 w; |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) trisc <= #1 TRIS_RST_VALUE; |
else |
if(trisc_we & valid_1) trisc <= #1 w; |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) option <= #1 OPT_RST_VALUE; |
else |
if(opt_we & valid_1) option <= #1 w[5:0]; |
|
always @(posedge clk) |
if(porta_we & valid_1) portaout <= #1 dout; |
|
always @(posedge clk) |
if(portb_we & valid_1) portbout <= #1 dout; |
|
always @(posedge clk) |
if(portc_we & valid_1) portcout <= #1 dout; |
|
always @(posedge clk) |
begin |
porta_r <= #1 portain; |
portb_r <= #1 portbin; |
portc_r <= #1 portcin; |
end |
|
/////////////////////////////////////////////////////////////////////// |
// Timer Logic |
|
//assign tmr0_next = tmr0_we ? dout : tmr0_cnt_en ? tmr0_plus_1 : tmr0; |
//assign tmr0_next = tmr0_we ? dout : tmr0_cnt_en ? (tmr0 + 1) : tmr0; |
|
|
mux2_8 u5( .sel(tmr0_we & valid_1), .in0(tmr0_next1), .in1(dout), .out(tmr0_next) ); |
mux2_8 u6( .sel(tmr0_cnt_en), .in0(tmr0), .in1(tmr0_plus_1), .out(tmr0_next1) ); |
inc8 u7( .in(tmr0), .out(tmr0_plus_1) ); |
|
|
always @(posedge clk) |
tmr0 <= #1 tmr0_next; |
|
presclr_wdt u8( .clk(clk), .rst(rst), .tcki(tcki), |
.option(option[5:0]), |
.tmr0_we(tmr0_we & valid_1), |
.tmr0_cnt_en(tmr0_cnt_en), .wdt_en(wdt_en), |
.wdt_clr(wdt_clr & valid_1), |
.wdt_to(wdt_to)); |
|
|
//////////////////////////////////////////////////////////////////////// |
// Programm Counter Logic |
|
always @(posedge clk) |
pc_r2 <= #1 pc_r; |
|
// 'inst_addr' is a duplication of the 'pc'. The only time when it is really needed |
// is when the program memory is not on the chip and we want to place the registers |
// directly in the IO pads to reduce Tcq (For example in a Xilinx FPGA implementation). |
// If the program memory is on the chip or if the implmentation allows feedback from |
// registers in the IO cells, this is not needed. Synopsys FPGA compiler appears to |
// make the correct decission either way, and gett rid of unneded logic ... |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) inst_addr <= #1 PC_RST_VECTOR; |
else inst_addr <= #1 pc_next; |
|
//synopsys sync_set_reset "rst" |
always @(posedge clk) |
if(rst) pc <= #1 PC_RST_VECTOR; |
else pc <= #1 pc_next; |
|
/* |
always @(pc_plus_1 or dout or pc_we or status or stack_out or |
pc_call or pc_goto or pc_retlw or instr_1) |
if(pc_we) pc_next = {status[6:5], 1'b0, dout}; |
else |
if(!pc_call & !pc_goto & !pc_retlw) pc_next = pc_plus_1; |
else |
if(pc_call) pc_next = {status[6:5], 1'b0, instr_1[7:0]}; |
else |
if(pc_goto) pc_next = {status[6:5], instr_1[8:0]}; |
else |
if(pc_retlw) pc_next = stack_out; |
*/ |
|
|
wire [10:0] pc_tmp1, pc_tmp2, pc_tmp3; |
wire pc_sel1; |
|
assign pc_tmp1 = {status[6:5], 1'b0, dout[7:0]}; |
assign pc_tmp2 = {status[6:5], 1'b0, instr_1[7:0]}; |
assign pc_tmp3 = {status[6:5], instr_1[8:0]}; |
assign pc_sel1 = (!pc_call & !pc_goto & !pc_retlw); |
|
mux2_11 u9 ( .sel(pc_we), .in0(pc_next1), .in1(pc_tmp1), .out(pc_next) ); |
mux2_11 u10( .sel(pc_sel1), .in0(pc_next2), .in1(pc_plus_1), .out(pc_next1) ); |
mux2_11 u11( .sel(pc_call), .in0(pc_next3), .in1(pc_tmp2), .out(pc_next2) ); |
mux2_11 u12( .sel(pc_goto), .in0(stack_out), .in1(pc_tmp3), .out(pc_next3) ); |
|
|
inc11 u13( .in(pc), .out(pc_plus_1) ); |
|
reg invalidate_1_r1, invalidate_1_r2; |
|
assign invalidate_1 = (pc_skz & z_out) | (pc_bset & bit_sel) | |
(pc_bclr & !bit_sel) | (invalidate_0 & valid_1) | invalidate_1_r1; |
|
|
always @(posedge clk) |
begin |
invalidate_1_r1 <= #1 (invalidate_0 & valid_1) | invalidate_1_r2; |
invalidate_1_r2 <= #1 (invalidate_0 & valid_1); |
end |
|
//assign bit_sel = src1[ instr_1[7:5] ]; |
mux8_1 u22( .sel(instr_1[7:5]), .in(src1), .out(bit_sel) ); |
|
sfifo4x11 u14( .clk(clk), .push(pc_call), .din(pc_r2), .pop(pc_retlw), .dout(stack_out) ); |
|
endmodule |
/trunk/verilog/core/risc_core_top.v
0,0 → 1,271
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Mini-RISC-1 //// |
//// Mini-Risc Core Top Levcel //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Rudolf Usselmann //// |
//// russelmann@hotmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT //// |
//// LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND //// |
//// FITNESS FOR A PARTICULAR PURPOSE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
|
`timescale 1ns / 10ps |
|
module mrisc_top( |
clk, rst_in, |
porta, portb, portc, |
tcki, |
wdt_en ); |
|
// Basic Core I/O. |
input clk; |
input rst_in; |
|
// I/O Ports |
inout [7:0] porta; |
inout [7:0] portb; |
inout [7:0] portc; |
|
input tcki; |
input wdt_en; |
|
//////////////////////////////////////////////////////////////////////// |
// |
// Local Wires |
// |
|
wire [10:0] inst_addr; |
wire [11:0] inst_data; |
|
wire [7:0] portain; |
wire [7:0] portbin; |
wire [7:0] portcin; |
|
wire [7:0] portaout; |
wire [7:0] portbout; |
wire [7:0] portcout; |
|
wire [7:0] trisa; |
wire [7:0] trisb; |
wire [7:0] trisc; |
|
wire block0, block1, wr_block0, wr_block1; |
|
wire [10:0] wr_adr; // This signals can be used to optionally |
wire [11:0] wr_data; // fill the internal ram from external memory |
wire we; |
|
wire [11:0] dout_unused; |
|
//////////////////////////////////////////////////////////////////////// |
// |
// IO Buffers |
// |
|
assign porta[0] = trisa[0] ? 1'bz : portaout[0]; |
assign porta[1] = trisa[1] ? 1'bz : portaout[1]; |
assign porta[2] = trisa[2] ? 1'bz : portaout[2]; |
assign porta[3] = trisa[3] ? 1'bz : portaout[3]; |
assign porta[4] = trisa[4] ? 1'bz : portaout[4]; |
assign porta[5] = trisa[5] ? 1'bz : portaout[5]; |
assign porta[6] = trisa[6] ? 1'bz : portaout[6]; |
assign porta[7] = trisa[7] ? 1'bz : portaout[7]; |
|
assign portb[0] = trisb[0] ? 1'bz : portbout[0]; |
assign portb[1] = trisb[1] ? 1'bz : portbout[1]; |
assign portb[2] = trisb[2] ? 1'bz : portbout[2]; |
assign portb[3] = trisb[3] ? 1'bz : portbout[3]; |
assign portb[4] = trisb[4] ? 1'bz : portbout[4]; |
assign portb[5] = trisb[5] ? 1'bz : portbout[5]; |
assign portb[6] = trisb[6] ? 1'bz : portbout[6]; |
assign portb[7] = trisb[7] ? 1'bz : portbout[7]; |
|
assign portc[0] = trisc[0] ? 1'bz : portcout[0]; |
assign portc[1] = trisc[1] ? 1'bz : portcout[1]; |
assign portc[2] = trisc[2] ? 1'bz : portcout[2]; |
assign portc[3] = trisc[3] ? 1'bz : portcout[3]; |
assign portc[4] = trisc[4] ? 1'bz : portcout[4]; |
assign portc[5] = trisc[5] ? 1'bz : portcout[5]; |
assign portc[6] = trisc[6] ? 1'bz : portcout[6]; |
assign portc[7] = trisc[7] ? 1'bz : portcout[7]; |
|
assign portain = porta; |
assign portbin = portb; |
assign portcin = portc; |
|
//////////////////////////////////////////////////////////////////////// |
// |
// Mini Risc Core |
// |
|
mrisc u0( |
clk, |
rst_in, |
|
inst_addr, |
inst_data, |
|
portain, |
portbin, |
portcin, |
|
portaout, |
portbout, |
portcout, |
|
trisa, |
trisb, |
trisc, |
|
tcki, |
wdt_en ); |
|
|
//////////////////////////////////////////////////////////////////////// |
// |
// Program memory |
// |
|
// Optional interface to fill the memory from external ROM |
assign wr_adr = 11'h0; |
assign wr_data = 12'h0; |
assign we = 1'b0; |
|
// Block selects |
assign block0 = ~inst_addr[10]; |
assign block1 = inst_addr[10]; |
assign wr_block0 = ~wr_adr[10]; |
assign wr_block1 = wr_adr[10]; |
|
|
RAMB4_S4_S4 u10( |
.CLKA( clk ), |
.CLKB( clk ), |
.RSTB( 1'b0 ), |
.RSTA( 1'b0 ), |
|
.DOA( inst_data[3:0] ), |
.ADDRA( inst_addr[9:0] ), |
.DIA( 4'h0 ), |
.ENA( block0 ), |
.WEA( 1'b0 ), |
|
.DOB( dout_unused[3:0] ), |
.ADDRB( wr_adr[9:0] ), |
.DIB( wr_data[3:0] ), |
.ENB( wr_block0 ), |
.WEB( we ) ); |
|
RAMB4_S4_S4 u11( |
.CLKA( clk ), |
.CLKB( clk ), |
.RSTB( 1'b0 ), |
.RSTA( 1'b0 ), |
|
.DOA( inst_data[7:4] ), |
.ADDRA( inst_addr[9:0] ), |
.DIA( 4'h0 ), |
.ENA( block0 ), |
.WEA( 1'b0 ), |
|
.DOB( dout_unused[7:4] ), |
.ADDRB( wr_adr[9:0] ), |
.DIB( wr_data[7:4] ), |
.ENB( wr_block0 ), |
.WEB( we ) ); |
|
RAMB4_S4_S4 u12( |
.CLKA( clk ), |
.CLKB( clk ), |
.RSTB( 1'b0 ), |
.RSTA( 1'b0 ), |
|
.DOA( inst_data[11:8] ), |
.ADDRA( inst_addr[9:0] ), |
.DIA( 4'h0 ), |
.ENA( block0 ), |
.WEA( 1'b0 ), |
|
.DOB( dout_unused[11:8] ), |
.ADDRB( wr_adr[9:0] ), |
.DIB( wr_data[11:8] ), |
.ENB( wr_block0 ), |
.WEB( we ) ); |
|
// Depending on how much memory you need and how much is |
// available in the device uncomment the below block |
/* |
RAMB4_S4_S4 u10( |
.CLKA( clk ), |
.CLKB( clk ), |
.RSTB( 1'b0 ), |
.RSTA( 1'b0 ), |
|
.DOA( inst_data[3:0] ), |
.ADDRA( inst_addr[9:0] ), |
.DIA( 4'h0 ), |
.ENA( block1 ), |
.WEA( 1'b0 ), |
|
.DOB( ), |
.ADDRB( wr_adr[9:0] ), |
.DIB( wr_data[3:0] ), |
.ENB( wr_block1 ), |
.WEB( we ) ); |
|
RAMB4_S4_S4 u11( |
.CLKA( clk ), |
.CLKB( clk ), |
.RSTB( 1'b0 ), |
.RSTA( 1'b0 ), |
|
.DOA( inst_data[7:4] ), |
.ADDRA( inst_addr[9:0] ), |
.DIA( 4'h0 ), |
.ENA( block1 ), |
.WEA( 1'b0 ), |
|
.DOB( ), |
.ADDRB( wr_adr[9:0] ), |
.DIB( wr_data[7:4] ), |
.ENB( wr_block1 ), |
.WEB( we ) ); |
|
RAMB4_S4_S4 u12( |
.CLKA( clk ), |
.CLKB( clk ), |
.RSTB( 1'b0 ), |
.RSTA( 1'b0 ), |
|
.DOA( inst_data[11:8] ), |
.ADDRA( inst_addr[9:0] ), |
.DIA( 4'h0 ), |
.ENA( block1 ), |
.WEA( 1'b0 ), |
|
.DOB( ), |
.ADDRB( wr_adr[9:0] ), |
.DIB( wr_data[11:8] ), |
.ENB( wr_block1 ), |
.WEB( we ) ); |
|
*/ |
|
|
|
endmodule |
/trunk/README.txt
0,0 → 1,119
|
This is a Mini-RISC CPU/Microcontroller that is mostly compatible with the |
PIC 16C57 from Microchip. |
|
|
Legal |
===== |
|
PIC, Microship, etc. are Trademarks of Microchip Technology Inc. |
|
I have no idea if implementing this core will or will not violate |
patents, copyrights or cause any other type of lawsuits. |
|
I provide this core AS IS, without any warrenties. If you decide to |
build this core, you are responsible for any legal resolutions, such |
as patents and copyrights, and perhaps others .... |
|
This source file(s) may be used and distributed without |
restriction provided that this copyright statement is not |
removed from the file and that any derivative work contains |
the original copyright notice and the associated disclaimer. |
|
THIS SOURCE FILE(S) IS/ARE PROVIDED "AS IS" AND WITHOUT ANY |
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT |
LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND |
FITNESS FOR A PARTICULAR PURPOSE. |
|
|
Motivation |
========== |
|
After seeing the "free_risc8" on the free-ip web site, I got excited |
and downloaded the core. Pretty soon I found out that it had many |
many errors and omissions from the original 16C57. So I started looking |
at the code. This is when I realized it was very badly designed and |
could not be made run faster. So, I sat down and wrote my own PIC IP |
core last night. A lot of work was spend in writing test code to ensure |
that it was 100% compatible from the software point of view. |
|
- A PIC compatible Microcontroller that runs a lot faster |
- Separate (External to the core) Program Memory |
- Options to extend the core |
|
|
Compatibility |
============= |
|
This design should be fully software compatible to the Microchip Implementation |
of the PIC 16C57, except for the following extensions: |
|
- Port A is full 8 bits wide |
- Hardware stack is 4 level deep [original 2 levels] (can be easily expanded) |
- Executions of instructions that modify the PC has become a lot more expensive |
due to the pipeline and execution of instructions on every cycle. |
Any instruction that writes to the PC (PC as destination (f), call, goto, retlw) |
now takes 4 cycles to execute (instead of 2 in the origianl implementation). |
The 4 'skip' instructions, remain as in the original implmentation: 1 cycle |
if not skipped, 2 cycles if skipped. |
- Sampling of IO ports might be off |
- Timer and watchdog might be off a few cycles |
|
|
Performance |
=========== |
|
- Single cycle instruction execution, except as noted above. |
- Here are results of some sample implementations: |
- Xilinx Spartan2 (Device: xc2s30-6-cs144): Fmax: 50Mhz, Utilization: 66%, Ports: Tsu: 2.2nS, Tcq: 7.7nS |
- Xilinx Virtex (Device: xcv50-4-cs144) : Fmax: 40Mhz, Utilization: 35%, Ports: Tsu: 3.0nS, Tcq: 6.2nS |
- Xilinx VirtexE (Device: xcv50e-8-cs144): Fmax: 66Mhz, Utilization: 35%, Ports: Tsu: 1.7nS, Tcq: 4.5nS |
Half of the cycle time is spend in routing delays. My guess is that by placing |
proper locatiuon contrains and guiding the back-end tools, a significant |
speed improvement can be achieved .... |
- I estimat about 25K gates with the xilinx primitives, (excluding Register |
File and Programm Memory). |
|
Implementing the core |
===================== |
|
The only file you should edit if you really want to implement this core, is the |
'primitives.v' file. It contains all parts that can be optimized, depending on |
the technology used. It includes memories, and arithmetic modules. |
I added a primitives_xilinx,v file and xilinx_primitives.zip which contain |
primitives for xilinx. |
'risc_core.v' is the top level without program memory and tristate Io buffers for ports. |
This is probably a good starting point if you want to instantiate the core in to a larger |
design. If you just want a PIC clone, take a loot at 'risc_core_top.v', it was written |
with Xilinx FPGAs in mind, but should be easily addaptred to other vendors FPGAs - just |
replace the memory blocks ... |
|
To-Do |
===== |
|
Things that need to be done |
|
1) Write more test/compliance test vectors |
- Verify that all instructions after a goto/call/retlw/write to PCL are not executed |
- Verify ALU |
- Timer and Watchdog tests |
- Perhaps some other ereas ? |
|
2) Extensions ? |
- I guess this is on a "as needed" basis |
- A friend suggested to add registers that can be shared by two or more cores in a MP type configuration |
|
Author |
====== |
|
I have been doing ASIC design, verification and synthesis for over 15 years. |
This core is only a "mid-night hack", and should used with caution. |
|
I'd also like to know if anyone will actually use this core. Please send me a |
note if you will ! |
|
Rudolf Usselmann |
russelmann@hotmail.com |
|
Feel free to send me comments, suggestions and bug reports. |
|