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