📄 risc_core.v
字号:
/////////////////////////////////////////////////////////////////////
//// ////
//// Mini-RISC-1 ////
//// Mini-Risc Core ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// D/L from: http://www.opencores.org/cores/minirisc/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: risc_core.v,v 1.3 2002/10/01 12:44:24 rudi Exp $
//
// $Date: 2002/10/01 12:44:24 $
// $Revision: 1.3 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: risc_core.v,v $
// Revision 1.3 2002/10/01 12:44:24 rudi
// Tweaked code a bit - trying to get it run faster ...
//
// Revision 1.2 2002/09/27 15:35:40 rudi
// Minor update to newer devices ...
//
//
//
//
//
//
//
//
//
//
//
`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 ),
.rst( rst ),
.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)
instr_1 <= #1 instr_0;
always @(posedge clk) // Basic Decode extracted directly from the instruction
begin
// 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) );
*/
reg instd_zero;
always @(posedge clk)
instd_zero <= #1 !(|inst_data[4:0]);
// Register File Read Port
assign rf_rd_bnk = fsr_next[6:5];
assign rf_rd_addr = instd_zero ? fsr_next[4:0] : instr_0[4:0];
// ALU OP
always @(posedge clk)
casex(instr_0) // synopsys full_case parallel_case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -