URL
https://opencores.org/ocsvn/minirisc/minirisc/trunk
Subversion Repositories minirisc
[/] [minirisc/] [trunk/] [verilog/] [core/] [risc_core.v] - Rev 7
Compare with Previous | Blame | View Log
///////////////////////////////////////////////////////////////////// //// //// //// 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: not supported by cvs2svn $ // 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 // 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] != 3'h0 )) ? 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 = 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) ); 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) ); 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; always @(posedge clk) if(rst) trisa <= #1 TRIS_RST_VALUE; else if(trisa_we & valid_1) trisa <= #1 w; always @(posedge clk) if(rst) trisb <= #1 TRIS_RST_VALUE; else if(trisb_we & valid_1) trisb <= #1 w; always @(posedge clk) if(rst) trisc <= #1 TRIS_RST_VALUE; else if(trisc_we & valid_1) trisc <= #1 w; 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 ... always @(posedge clk) if(rst) inst_addr <= #1 PC_RST_VECTOR; else inst_addr <= #1 pc_next; 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