OpenCores
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.
 

powered by: WebSVN 2.1.0

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