Project: mrisclab1

Contents

Verilog Files

mrisclab1.v
clock_divider.v
decimal_counter.v
divide_by_10.v
divide_by_50.v
EX_stage.v
hex_7seg.v
ID_stage.v
IF_stage.v
iformat.v
MEM_stage.v
mrisc1.v
alu.v
muxi.v
reg_file.v
reset_delay.v
rformat.v
rom1.v

Quartus Files

fit.summary
tan.summary

Verilog Files

mrisclab1.v

module mrisclab1(
  // Clock Input (50 MHz)
  input  CLOCK_50,
  //  Push Buttons
  input  [3:0]  KEY,
  //  DPDT Switches 
  input  [17:0]  SW,
  //  7-SEG Displays
  output  [6:0]  HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7,
  //  LEDs
  output  [8:0]  LEDG,  //  LED Green[8:0]
  output  [17:0]  LEDR,  //  LED Red[17:0]
  // LCD Module
  output LCD_ON,   // LCD power on/off
  output LCD_BLON, // LCD back light on/off
  output LCD_RW,   // LCD Read/Write select, 0 = Write, 1 = Read
  output LCD_EN,   // LCD Enable
  output LCD_RS,   // LCD Command/Data Select, 0 = Command, 1 = Data
  inout [7:0] LCD_DATA, // LCD Data bus (8 bits)
  //  GPIO Connections
  inout  [35:0]  GPIO_0, GPIO_1
);

// turn LCD on
/*
assign LCD_ON = 1'b1;
assign LCD_BLON = 1'b1;
*/

//  set all inout ports to tri-state
assign  GPIO_0    =  36'hzzzzzzzzz;
assign  GPIO_1    =  36'hzzzzzzzzz;

wire [6:0] myclock;
wire reset_n = KEY[0];

// Setup clock divider
clock_divider cdiv(CLOCK_50,reset_n,myclock);
assign GPIO_0[6:0] = myclock;

// Connect clock divider to green LEDs
// LEDG[7:6] = cs
//assign LEDG[8:0] =  {7'd00,myclock[1:0]}; //{4'h00, myclock[4:0] };
assign LEDG[8:0] = {1'b0,clk,we,1'b0,active[4:0]};

// Connect dip switches to red LEDS
assign LEDR[17:0] = SW[17:0];

// map 7-segment displays

// blank unused digits
wire [6:0] blank = ~7'h00;
hex_7seg seg0(results[3:0],HEX0);
hex_7seg seg1(results[7:4],HEX1);
hex_7seg seg2(results[11:8],HEX2);
hex_7seg seg3(results[15:12],HEX3);
assign HEX4 = blank;
hex_7seg seg5(rd[3:0],HEX5);
//assign HEX5 = blank;
//assign HEX6 = blank;
//assign HEX7 = blank;
// program counter
hex_7seg seg6(pc[3:0],HEX6);
hex_7seg seg7(pc[7:4],HEX7);

// one-second clock
wire clk = myclock[0];

// memory bus
/*
wire [7:0] addr;
wire [15:0] q, data;
wire we;
*/

// i/o bus
/*
wire [1:0] io_addr;
wire [15:0] qio;
wire [2:0] cs;
wire io_we;

controller dev1(
    .clk(clk),
    // mem bus
    .addr(addr),
    .q(q),
    .data(data),
    .we(we),
    // i/o bus
    .io_addr(io_addr),
    .qio(qio),
    .cs(cs),
    .io_we(io_we)
);

switches u0(
    .clk(clk),
    .cs(cs[0]),
    .addr(io_addr),
    .data(qio),
    .we(io_we), 
    // DE2 end
    .sw(SW)
);



segments u1(
    .clk(clk),
    .cs(cs[1]),
    .addr(io_addr),
    .data(qio),
    .we(io_we),
    // DE2 end
    .HEX3(HEX3),
    .HEX2(HEX2),
    .HEX1(HEX1),
    .HEX0(HEX0)
);

LCD_controller u2(

    .clk(clk),
    .cs(cs[2]),
    .addr(io_addr),
    .data(qio),
    .we(io_we),
    // DE2 end
    .LCD_RS(LCD_RS), 
    .LCD_EN(LCD_EN), 
    .LCD_RW(LCD_RW),
    .DATA_BUS(LCD_DATA)
);
*/

wire [7:0] pc;
wire [31:0] ir, results;
wire [4:0] rd, active;
wire we;

mrisc1 cpu(
    .clock(clk), 
    .reset(reset_n),
    .pc(pc),
    .ir(ir), 
    .we(we), 
    .rd(rd), 
    .results(results),
    .active(active)
);

/*
dcpu2 cpu( 
    .clk(clk), 
    .reset_n(reset_n), 
    .loopback(1'b1),
    .pc(pc),
    // memory bus
    .addr(addr),
    .q(q),
    .data(data),
    .we(we)
);
*/


endmodule

clock_divider.v

module clock_divider(CLK,RST,clock);
input CLK,RST;
output [6:0] clock;
wire clk_1Mhz,clk_100Khz,clk_10Khz,clk_1Khz,clk_100hz,clk_10hz,clk_1hz;

assign clock = {clk_1Mhz,clk_100Khz,clk_10Khz,clk_1Khz,clk_100hz,clk_10hz,clk_1hz};

divide_by_50 d6(clk_1Mhz,CLK,RST);
divide_by_10 d5(clk_100Khz,clk_1Mhz,RST);
divide_by_10 d4(clk_10Khz,clk_100Khz,RST);
divide_by_10 d3(clk_1Khz,clk_10Khz,RST);
divide_by_10 d2(clk_100hz,clk_1Khz,RST);
divide_by_10 d1(clk_10hz,clk_100hz,RST);
divide_by_10 d0(clk_1hz,clk_10hz,RST);
endmodule

decimal_counter.v

module decimal_counter(A,OVERFLOW,CLK,RST);
input CLK, RST;
output OVERFLOW;
output [3:0] A;
reg OVERFLOW;
reg [3:0] A;
always @ (posedge CLK or negedge RST)
if (~RST) begin
    OVERFLOW <= 1'b0;
    A <= 4'b0000;
end
else if (A<9) begin
    A <= A + 1'b1;
    OVERFLOW <= 1'b0;
end
else begin
    A <= 4'b0000;
    OVERFLOW <= 1'b1;
end
endmodule

divide_by_10.v

module divide_by_10(Q,CLK,RST);
input CLK, RST;
output Q;
reg Q;
reg [2:0] count;
always @ (posedge CLK or negedge RST)
    begin
        if (~RST)
            begin
                Q <= 1'b0;
                count <= 3'b000;
            end
        else if (count < 4)
            begin 
                 count <= count+1'b1;
            end
        else 
            begin
                count <= 3'b000;
                Q <= ~Q;
            end
    end
endmodule

divide_by_50.v

module divide_by_50(Q,CLK,RST);
input CLK, RST;
output Q;
reg Q;
reg [4:0] count;
always @ (posedge CLK or negedge RST)
    begin
        if (~RST)
            begin
                Q <= 1'b0;
                count <= 5'b00000;
            end
        else if (count < 24)
            begin 
                 count <= count+1'b1;
            end
        else 
            begin
                count <= 5'b00000;
                Q <= ~Q;
            end
    end
endmodule

EX_stage.v

module EX_stage(
    input [34:0] EX_in,
    input [31:0] qa, qb, immedse, 
    output [25:0] EX_out, 
    output [31:0] qd
);
wire active;
wire [5:0] op;
wire [6:0] fn;
wire [4:0] rd,shf;
wire [5:0] control;
wire [1:0] muxc;

assign {active,halt,shf,op,fn,control,muxc,rd} = EX_in;

wire [31:0] dmuxi; // muxi output
muxi mux1(
    .dst(dmuxi),
    .b(qb),
    .immedse(immedse),
    .control(muxc)
    );
    
wire [31:0] dalu; // alu output

wire zero, ovfl;

alu my_alu(
    .a(qa),
    .b(dmuxi),
    .control(control[3:0]),
    .c(dalu)
    );
    
assign qd = dalu;
assign EX_out = {active, halt, op, fn, control, rd};

endmodule

hex_7seg.v

module hex_7seg(hex_digit,seg);
input [3:0] hex_digit;
output [6:0] seg;
reg [6:0] seg;
// seg = {g,f,e,d,c,b,a};
// 0 is on and 1 is off

always @ (hex_digit)
case (hex_digit)
        4'h0: seg = 7'b1000000;
        4'h1: seg = 7'b1111001;     // ---a----
        4'h2: seg = 7'b0100100;     // |      |
        4'h3: seg = 7'b0110000;     // f      b
        4'h4: seg = 7'b0011001;     // |      |
        4'h5: seg = 7'b0010010;     // ---g----
        4'h6: seg = 7'b0000010;     // |      |
        4'h7: seg = 7'b1111000;     // e      c
        4'h8: seg = 7'b0000000;     // |      |
        4'h9: seg = 7'b0011000;     // ---d----
        4'ha: seg = 7'b0001000;
        4'hb: seg = 7'b0000011;
        4'hc: seg = 7'b1000110;
        4'hd: seg = 7'b0100001;
        4'he: seg = 7'b0000110;
        4'hf: seg = 7'b0001110;
endcase

endmodule

ID_stage.v

module ID_stage(input [34:0] ID_in, output [32:0] ID_out);

wire active, halt;
wire [5:0] op;
wire [6:0] fn;
wire [4:0] ra,rb,rd,shf;

assign {active,halt,shf,fn,op,rd,rb,ra} = ID_in;

// instantiate r-format control unit
wire [5:0] rcontrol;
rformat unit1(
    .fn(fn),
    .control(rcontrol)
);
    
// instantiate i-format control unit
wire [5:0] icontrol;
wire [1:0] muxi;
iformat unit2(
    .op(op),
    .control(icontrol),
    .muxi(muxi)
    );

wire flag = (op==0);
wire [5:0] control = (flag? rcontrol: icontrol);
wire [1:0] muxc = (flag? 2'b00: muxi);
assign ID_out = {active,halt, op,fn,shf,control,muxc,rd};

endmodule

IF_stage.v

module IF_stage(input [31:0] ir, 
    output [34:0] IF_out, output [31:0] immedse);

wire [5:0] op;
reg [6:0] fn;
reg [4:0] ra,rb,rd;

// COMMON FIELDS
`define RT 20:16
`define RS 25:21
`define OP 31:26
// RFORMAT FIELDS
`define FN 5:0
`define SH 10:6
`define RD 15:11
// IFORMAT
`define IMM 15:0
wire [4:0] shf = ir[`SH];

assign op = ir[`OP];
assign immedse = {(ir[15]?16'hffff:16'h0000),ir[`IMM]};

always
begin
    ra <= ir[`RS];
    if (op>1)
    begin
        rd <= ir[`RT];
        fn <= {1'b0,ir[`FN]};
        rb <= 5'h0;
    end
    else if (op==6'b1)
    begin
        fn <= {1'b1,ir[`FN]};
        rd <= 5'd0;
        rb <= 5'd0;
    end
    else
    begin
        fn <= {1'b0,ir[`FN]};
        rd <= ir[`RD];
        rb <= ir[`RT];
    end
end

wire halt = ir == 32'h04010000;
wire active = (ir != 0) && ~halt;
assign IF_out = {active,halt, shf,fn,op,rd,rb,ra};

endmodule

iformat.v

module iformat(input [5:0] op,output [5:0] control, output reg [1:0] muxi);

// opcodes    
`include "opcodes.txt"

reg [3:0] acontrol;
reg [1:0] mem;
`define LW_C 1
`define SW_C 2

always
    case (op)
    ADDI: 
    begin
        acontrol <= 4'b0000; // add
        muxi <= 2'b01; // se 
    end
    ADDIU:
    begin
        acontrol <= 4'b0010; // addu
        muxi <= 2'b01; // se
    end
    ANDI: 
    begin
        acontrol <= 4'b0100; // andi
        muxi <= 2'b10;
    end
    ORI: 
    begin
        acontrol <= 4'b0101; // ori
        muxi <= 2'b10;
    end
    XORI: 
    begin 
        acontrol <= 4'b0110; // xor
        muxi <= 2'b10;
    end
    LUI: 
    begin
        acontrol <= 4'b0101; // or
        muxi <= 2'b11; // hi
    end
    SLTI:
    begin
        acontrol <= 4'b1001;
        muxi = 2'b01;
    end
    SLTIU:
    begin
        acontrol = 4'b1011;
        muxi = 2'b01;
    end
    LW:
    begin
        acontrol = 4'b0000;
        muxi = 2'b01;
    end
    SW:
    begin
        acontrol = 4'b0000;
        muxi = 2'b01;
    end
    default: 
    begin
        acontrol <= 4'b0000;
        muxi <= 2'b00; // nop
    end
    endcase

always
    case (op)
    LW: 
        mem <= `LW_C;
    SW:
        mem <= `SW_C;
    default:
        mem <= 2'b00;
    endcase
    
assign control = {mem,acontrol};    
    
endmodule

MEM_stage.v

module MEM_stage(
    input [25:0] MEM_in,
    output [6:0] MEM_out,
    input [31:0] qd, qm,
    output [31:0] qe,
    output write_enable
);
wire active, halt;
wire [5:0] op;
wire [6:0] fn;
wire [4:0] rd,shf;
wire [5:0] control;
wire [1:0] muxc;

assign {active,halt,op,fn,control,rd} = MEM_in;


assign qe = qd;
assign write_enable = active;


assign MEM_out = {active, halt, rd};

endmodule

mrisc1.v

module mrisc1(input clock, input reset, 
    output reg [7:0] pc, output [31:0] ir, 
    output we, output [4:0] rd, output [31:0] results,
    output [4:0] active
);

// instantiate memory
wire [7:0] next_pc;
assign next_pc = pc + 1'b1;

rom1 inst_cache(
    .address(next_pc),
    .clock(clock),
    .q(ir)
);

always @(posedge clock or negedge reset)
    if (!reset) 
        pc <= 8'hff; // so that next_pc starts at zero
    else 
        pc <= next_pc;

// Instantiate register file

wire [31:0] da, db, dc;
wire [4:0] ra, rb, rc;
wire write_enable;

assign {rb, ra} = ID_in[9:0]; 

reg_file regs(
    .clock(clock),
    .da(da),
    .db(db),
    .dc(dc),
    .ra(ra),
    .rb(rb),
    .rc(rc),
    .write_enable(write_enable)
    );

// fetch stage

wire [34:0] IF_out;
reg [31:0] immedse2, immedse3;
wire [31:0] immedse1, jump_target;
assign jump_target = {6'h0,ir[25:0]};
IF_stage stage1(ir,IF_out,immedse1);

// decode stage

reg [34:0] ID_in;
wire [32:0] ID_out;
ID_stage stage2(ID_in,ID_out);

// execute stage

reg [32:0] EX_in;
wire [25:0] EX_out;
wire [31:0] qd;

EX_stage stage3(EX_in,da,db,immedse3,EX_out,qd);

// memory stage

wire [32:0] qm = 0;
reg [25:0] MEM_in;
wire [6:0] MEM_out;

MEM_stage stage4(MEM_in,MEM_out,qd,qm,dc,write_enable);


//----------------------------------------------------------
// send the output of the ALU back to the register file

//assign dc = dalu;
assign rc = MEM_out[4:0];
assign we = write_enable;
assign rd = rc;
assign results = dc; // also send output outside the module for display
assign active = {1'b0, MEM_out[6], EX_out[25], ID_out[32], IF_out[34]};

always @(posedge clock)
begin
    ID_in <= IF_out;
    immedse3 <= immedse2;
    immedse2 <= immedse1;
    EX_in <= ID_out;
    MEM_in <= EX_out;
end

endmodule

alu.v

/*
*   control:
*    000  add, signed
*    001  subtract, signed
*    010  add, unsigned
*    011  subtract, unsigned
* --------------------------------------------
*    100  AND
*    101  OR
*    110  XOR
*    111  NOR
*/  
module alu(a,b,control,c,zero,neg,ovfl);
parameter BITS = 32;
input [BITS-1:0] a, b;
input [3:0] control;
output [BITS-1:0] c;
output zero, neg, ovfl;

wire subtract;
assign subtract = control[0];

// add-subtract unit
wire [BITS-1:0] sum;
wire [BITS-1:0] bn;
wire cin, cout;
assign cin = subtract;
assign bn = (subtract? ~b: b);
assign {cout, sum} = a+bn+cin;

// logic unit
reg [BITS-1:0] out;
always
    case (control[1:0])
    2'b00: out = a&b;
    2'b01: out = a|b;
    2'b10: out = a^b;
    2'b11: out = ~(a|b);
    endcase

wire zero, sgn, unsgn;
assign zero = ~(|sum);
assign sgn  = (sum[BITS-1]? (~a[BITS-1])&(~bn[BITS-1]): a[BITS-1]&bn[BITS-1] );
assign unsgn = cout^subtract;
assign ovfl = (control[1]? unsgn: sgn);
assign neg = (control[1]? unsgn: sum[BITS-1]);

assign c = control[3]? {31'h0,neg}: (control[2]? out: sum);

endmodule

muxi.v

/*
*   control:
*    00  b
*    01  immedse, (immed sign-extended)
*    10  {16'h0000, immed} (not sign-extended)
*    11  {immed, 16'h0000}
*/
module muxi
#(parameter BITS = 32)
(
    output reg [BITS-1:0] dst, 
    input [BITS-1:0] b, immedse,
    input [1:0] control
);

always
    case (control)
    2'b00: dst = b;
    2'b01: dst = immedse;
    2'b10: dst = {16'h0000, immedse[15:0]};
    2'b11: dst = {immedse[15:0],16'h0000};
    endcase
endmodule

reg_file.v

module reg_file(clock,da,db,dc,ra,rb,rc,write_enable);
parameter BITS = 32;
input [BITS-1:0] dc;
output [BITS-1:0] da,db;
input [4:0] ra,rb,rc;
input clock, write_enable;
reg [BITS-1:0] r[0:31];

wire aflag = write_enable && (rc==ra) && ra;
wire bflag = write_enable && (rc==rb) && rb;

wire [BITS-1:0] qa,qb;

always @(posedge clock)
begin
    if (write_enable) r[rc] = dc;
end

assign    qa = ra? r[ra]: 0;
assign    qb = rb? r[rb]: 0;


// ensure read after write
assign da = aflag? dc: qa;
assign db = bflag? dc: qb;

endmodule            

reset_delay.v

module    Reset_Delay(iCLK,oRESET);
input        iCLK;
output reg    oRESET;
reg    [19:0]    Cont;

always@(posedge iCLK)
begin
    if(Cont!=20'hFFFFF)
    begin
        Cont    <=    Cont+1'b1;
        oRESET    <=    1'b0;
    end
    else
    oRESET    <=    1'b1;
end

endmodule

rformat.v

module rformat(input [5:0] fn, output [5:0] control);

// opcodes    
`include "opcodes.txt"

reg [3:0] acontrol;

always
    case (fn)
    NOR: acontrol = 4'b0111;
    AND: acontrol = 4'b0100;
    OR: acontrol = 4'b0101;
    XOR: acontrol = 4'b0110;
    ADD: acontrol = 4'b0000;
    ADDU: acontrol = 4'b0010;
    SUB: acontrol = 4'b0001;
    SUBU: acontrol = 4'b0011;
    SLT:  acontrol = 4'b1001;
    SLTU: acontrol = 4'b1011;
    default: acontrol = 4'b0000;
    endcase
    
assign control = {2'b00,acontrol};
    
endmodule

rom1.v

// Quartus II Verilog Template
// Single Port ROM

module rom1
#(parameter DATA_WIDTH=32, parameter ADDR_WIDTH=8)
(
    input [(ADDR_WIDTH-1):0] address,
    input clock,  
    output reg [(DATA_WIDTH-1):0] q
);

    // Declare the ROM variable
    reg [DATA_WIDTH-1:0] rom[0:2**ADDR_WIDTH-1];

    // Initialize the ROM with $readmemb.  Put the memory contents
    // in the file single_port_rom_init.txt.  Without this file,
    // this design will not compile.
    // See Verilog LRM 1364-2001 Section 17.2.8 for details on the
    // format of this file.

    initial
    begin
        $readmemh("inst.txt", rom);
    end

    always @ (posedge clock)
    begin
        q <= rom[address];
    end

endmodule

Quartus Compilation Summary

fit.summary

Fitter Status : Successful - Thu Apr 26 12:13:36 2012
Quartus II Version : 9.0 Build 235 06/17/2009 SP 2 SJ Web Edition
Revision Name : mrisclab1
Top-level Entity Name : mrisclab1
Family : Cyclone II
Device : EP2C35F672C6
Timing Models : Final
Total logic elements : 479 / 33,216 ( 1 % )
    Total combinational functions : 459 / 33,216 ( 1 % )
    Dedicated logic registers : 148 / 33,216 ( < 1 % )
Total registers : 148
Total pins : 191 / 475 ( 40 % )
Total virtual pins : 0
Total memory bits : 10,240 / 483,840 ( 2 % )
Embedded Multiplier 9-bit elements : 0 / 70 ( 0 % )
Total PLLs : 0 / 4 ( 0 % )

tan.summary

--------------------------------------------------------------------------------------
Timing Analyzer Summary
--------------------------------------------------------------------------------------

Type           : Worst-case tco
Slack          : N/A
Required Time  : None
Actual Time    : 45.422 ns
From           : mrisc1:cpu|reg_file:regs|r_0_bypass[4]
To             : HEX3[0]
From Clock     : CLOCK_50
To Clock       : --
Failed Paths   : 0

Type           : Worst-case tpd
Slack          : N/A
Required Time  : None
Actual Time    : 9.765 ns
From           : SW[16]
To             : LEDR[16]
From Clock     : --
To Clock       : --
Failed Paths   : 0

Type           : Clock Setup: 'CLOCK_50'
Slack          : N/A
Required Time  : None
Actual Time    : 42.12 MHz ( period = 23.742 ns )
From           : mrisc1:cpu|reg_file:regs|r_0_bypass[4]
To             : mrisc1:cpu|reg_file:regs|altsyncram:r_rtl_0|altsyncram_99e1:auto_generated|ram_block1a0~porta_datain_reg19
From Clock     : CLOCK_50
To Clock       : CLOCK_50
Failed Paths   : 0

Type           : Total number of failed paths
Slack          : 
Required Time  : 
Actual Time    : 
From           : 
To             : 
From Clock     : 
To Clock       : 
Failed Paths   : 0

--------------------------------------------------------------------------------------


Maintained by John Loomis, last updated Fri May 18 11:39:49 2012