risclab1.v
module risclab1( // 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] // GPIO Connections inout [35:0] GPIO_0, GPIO_1 ); // 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 LEDG[8:1] = 8'h00; assign LEDG[0] = active; // Connect dip switches to red LEDS assign LEDR[17:0] = SW[17:0]; // map to 7-segment displays wire [3:0] rx; assign rx = {1'b0, ra[2:0]}; hex_7seg_blanking dsp4(rx,HEX4,SW[3]); wire [15:0] dx; hex_7seg_blanking dsp0(dx[3:0],HEX0,1'b0); hex_7seg_blanking dsp1(dx[7:4],HEX1,1'b0); hex_7seg_blanking dsp2(dx[11:8],HEX2,1'b0); hex_7seg_blanking dsp3(dx[15:12],HEX3,1'b0); wire [6:0] blank = ~7'h00; assign HEX5 = blank; //assign HEX6 = blank; assign HEX7 = blank; hex_7seg_blanking dsp6({2'h0,state},HEX6,~active); wire [15:0] qa,qd; wire [2:0] ra,rd; assign ra = active? rd: SW[2:0]; assign dx = SW[3]? ncycles: (active? qd: qa); wire we; regfile u1( .clk(CLOCK_50), .ra(ra), .qa(qa), .rd(rd), .we(we), .qd(qd) ); wire clk = (SW[17]? myclock[0]: CLOCK_50); wire active; wire [15:0] ncycles; wire [1:0] state; risc_cpu cpu0( .clk(clk), .reset_n(reset_n), .rd(rd), .qd(qd), .rwe(we), .cpu_active(active), .cpu_state(state), .ncycles(ncycles) ); endmodule
risc_cpu.v
`define OP 2:0 `define PC 11:4 `define RD 14:12 `define RA 18:16 `define RB 22:20 `define IM 35:24 `define OPHALT 3 `define OPSW 40 `define OPLW 41 `define OPBNE 42 `define OPJALR 43 module risc_cpu #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=5) ( input clk, reset_n, output [2:0] rd, output [(DATA_WIDTH-1):0] qd, output rwe, output cpu_active, output [1:0] cpu_state, output reg [(DATA_WIDTH-1):0] ncycles ); wire [(ADDR_WIDTH-1):0] addr; wire [2:0] ra, rb; wire [(DATA_WIDTH-1):0] q, qi, qa, qb; wire [47:0] IF; reg [47:0] ID; reg we; assign cpu_active = active; assign cpu_state = state; single_port_ram dev1( .data(qb), .addr(addr), .we(we), .clk(clk), .q(q) ); assign rwe = state==IFE; regfile dev2( .clk(clk), .we(rwe), .ra(ra), .qa(qa), .rb(rb), .qb(qb), .rd(rd), .qd(qd) ); reg [4:0] pc; //wire [(DATA_WIDTH-1):0] q; wire [2:0] opcode; // Instruction Fetch (IF) reg [15:0] inst; reg active; wire ma2 = (ID[`OPSW] || ID[`OPLW]); //wire [15:0] qi; assign qi = (active? (ma2? inst: q): 16'h0000); assign opcode = qi[15:13]; // opcodes `include "opcodes.txt" wire op_add = opcode==ADD; wire op_nand = opcode==NAND; wire op_sw = opcode==SW; wire op_lw = opcode==LW; wire op_bne = opcode==BNE; wire op_jalr = opcode==JALR; wire flag1 = op_sw||op_bne; // no write-back wire flag2 = op_add||op_nand; // RRR format wire [2:0] rd1 = flag1? 3'h0: qi[12:10]; assign ra = qi[9:7]; assign rb = flag2? qi[2:0]: (flag1? qi[12:10]: 3'h0); assign IF[`OP] = opcode; assign IF[`OPHALT] = (qi==16'he071); // is halt assign IF[`PC] = pc; assign IF[`RD] = rd1; assign IF[`RA] = ra; assign IF[`RB] = rb; assign IF[`IM] = qi[9:0]; assign IF[`OPSW] = op_sw; assign IF[`OPLW] = op_lw; assign IF[`OPBNE] = op_bne; assign IF[`OPJALR] = op_jalr; wire memory_access = (IF[`OPSW] || IF[`OPLW]); //reg [(ADDR_WIDTH-1):0] jump; wire [(ADDR_WIDTH-1):0] jump = do_jump? qa[(ADDR_WIDTH-1):0]: (ID[`OPBNE]? d1[(ADDR_WIDTH-1):0]: 5'h00); wire do_branch = ID[`OPBNE] && (qa!=qb); wire do_jump = ID[`OPJALR]; wire [4:0] nextpc = pc + 1'b1; wire [4:0] newpc = (do_jump||do_branch? jump: nextpc); reg [4:0] maddr; assign addr = (state==MEM? d1: newpc ); wire [15:0] d1; wire [4:0] npc = ID[`PC] + 1'b1; assign rd = ID[`RD]; alu dev3( .a(qa), .b(qb), .pc({11'h000,npc}), .im10(ID[`IM]), .d(d1), .opcode(ID[`OP]) ); // writeback register multiplexer assign qd = (ID[`OPLW]? q: d1); reg [1:0] state; localparam RESET = 2'h0, IFE = 2'h1, MEM = 2'h2, HALT = 2'h3; wire [47:0] BLANK = 48'h0000_0000_0000; always @(posedge clk, negedge reset_n) begin if (!reset_n) begin active <= 1'b0; inst <= 16'h0000; pc <= 5'h1F; ID <= BLANK; state <= RESET; end else case (state) RESET: begin active <= 1'b0; state <= IFE; end IFE: begin active <= 1'b1; pc <= addr; if (do_jump) begin if (ID[`OPHALT]) state <= HALT; ID <= BLANK; end else if (do_branch) ID <= BLANK; else begin ID <= IF; if (memory_access) begin state <= MEM; we <= IF[`OPSW]; end end end MEM: begin state <= IFE; inst <= q; we <= 1'b0; end default: begin active <= 1'b0; state <= HALT; end endcase end always @(posedge clk or negedge reset_n) begin if (!reset_n) ncycles <= 16'h0000; else if (state==IFE || state==MEM) ncycles <= ncycles + 1'b1; end endmodule
alu.v
module alu( input [15:0] a, b, pc, input [9:0] im10, output reg [15:0] d, input [2:0] opcode ); `include "opcodes.txt" wire [15:0] seim = im10[6]? {9'h1FF,im10[6:0]}:{9'h000,im10[6:0]}; wire [15:0] sum = a + seim; always case (opcode) ADD: d <= a + b; ADDI: d <= sum; NAND: d <= ~(a&b); LUI: d <= {im10,6'h00}; SW: d <= sum; LW: d <= sum; BNE: d <= pc+seim; JALR: d <= pc; endcase endmodule
regfile.v
// The register file is a triple-port RAM // with two read addresses and a write address. // It is implemented with two double-port RAMs module regfile #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=3) ( input clk, input [(ADDR_WIDTH-1):0] ra, rb, rd, output [(DATA_WIDTH-1):0] qa, qb, input [(DATA_WIDTH-1):0] qd, input we ); double_port port1( .clk(clk), .we(we), .ra(ra), .rd(rd), .qa(qa), .qd(qd) ); double_port port2( .clk(clk), .we(we), .ra(rb), .rd(rd), .qa(qb), .qd(qd) ); endmodule module double_port #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=3) ( input [(DATA_WIDTH-1):0] qd, input [(ADDR_WIDTH-1):0] ra, rd, input we, clk, output [(DATA_WIDTH-1):0] qa ); // Declare the RAM variable reg [DATA_WIDTH-1:0] ram[0:2**ADDR_WIDTH-1]; // Initialize the RAM with $readmemb. Put the memory contents // in the data file. 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("registers.txt", ram); end // Variable to hold the registered read address reg [ADDR_WIDTH-1:0] ra_reg; always @ (posedge clk) begin // Write if (we) ram[rd] <= qd; end always @ (posedge clk) ra_reg <= ra; // Continuous assignment implies read returns NEW data. // This is the natural behavior of the TriMatrix memory // blocks in Single Port mode. assign qa = (ra_reg? ram[ra_reg]:16'h0000); 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
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
hex_7seg_blanking.v
module hex_7seg_blanking( input [3:0] hex_digit, output [6:0] seg, input blank_display ); reg [6:0] segm; // segm = {g,f,e,d,c,b,a}; // 0 is on and 1 is off always @ (hex_digit) case (hex_digit) 4'h0: segm = ~7'h3F; 4'h1: segm = ~7'h06; // ---a---- 4'h2: segm = ~7'h5B; // | | 4'h3: segm = ~7'h4F; // f b 4'h4: segm = ~7'h66; // | | 4'h5: segm = ~7'h6D; // ---g---- 4'h6: segm = ~7'h7D; // | | 4'h7: segm = ~7'h07; // e c 4'h8: segm = ~7'h7F; // | | 4'h9: segm = ~7'h67; // ---d---- 4'ha: segm = ~7'h77; 4'hb: segm = ~7'h7C; 4'hc: segm = ~7'h39; 4'hd: segm = ~7'h5E; 4'he: segm = ~7'h79; 4'hf: segm = ~7'h71; endcase wire [6:0] blank = ~7'h00; //assign blank_out = (hex_digit==4'b0000) && blank_in; assign seg = (blank_display? blank: segm); endmodule
single_port_ram.v
// Quartus II Verilog Template // Single port RAM with single read/write address module single_port_ram #(parameter DATA_WIDTH=16, parameter ADDR_WIDTH=5) ( input [(DATA_WIDTH-1):0] data, input [(ADDR_WIDTH-1):0] addr, input we, clk, output [(DATA_WIDTH-1):0] q ); // Declare the RAM variable reg [DATA_WIDTH-1:0] ram[0:2**ADDR_WIDTH-1]; // Initialize the RAM 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("prog2.txt", ram); end // Variable to hold the registered read address reg [ADDR_WIDTH-1:0] addr_reg; always @ (posedge clk) begin // Write if (we) ram[addr] <= data; addr_reg <= addr; end // Continuous assignment implies read returns NEW data. // This is the natural behavior of the TriMatrix memory // blocks in Single Port mode. assign q = ram[addr_reg]; endmodule
fit.summary
Fitter Status : Successful - Wed Apr 21 12:50:34 2010 Quartus II Version : 9.0 Build 235 06/17/2009 SP 2 SJ Web Edition Revision Name : risclab1 Top-level Entity Name : risclab1 Family : Cyclone II Device : EP2C35F672C6 Timing Models : Final Total logic elements : 422 / 33,216 ( 1 % ) Total combinational functions : 417 / 33,216 ( 1 % ) Dedicated logic registers : 148 / 33,216 ( < 1 % ) Total registers : 148 Total pins : 178 / 475 ( 37 % ) Total virtual pins : 0 Total memory bits : 896 / 483,840 ( < 1 % ) Embedded Multiplier 9-bit elements : 0 / 70 ( 0 % ) Total PLLs : 0 / 4 ( 0 % )
tan.summary
-------------------------------------------------------------------------------------- Timing Analyzer Summary -------------------------------------------------------------------------------------- Type : Worst-case tsu Slack : N/A Required Time : None Actual Time : 4.320 ns From : KEY[0] To : risc_cpu:cpu0|we From Clock : -- To Clock : CLOCK_50 Failed Paths : 0 Type : Worst-case tco Slack : N/A Required Time : None Actual Time : 36.620 ns From : risc_cpu:cpu0|regfile:dev2|double_port:port1|altsyncram:ram_rtl_2|altsyncram_p7j1:auto_generated|ram_block1a0~portb_address_reg2 To : HEX3[0] From Clock : CLOCK_50 To Clock : -- Failed Paths : 0 Type : Worst-case tpd Slack : N/A Required Time : None Actual Time : 15.491 ns From : SW[3] To : HEX3[0] From Clock : -- To Clock : -- Failed Paths : 0 Type : Worst-case th Slack : N/A Required Time : None Actual Time : 8.801 ns From : KEY[0] To : risc_cpu:cpu0|we From Clock : -- To Clock : CLOCK_50 Failed Paths : 0 Type : Clock Setup: 'CLOCK_50' Slack : N/A Required Time : None Actual Time : 41.49 MHz ( period = 24.104 ns ) From : risc_cpu:cpu0|regfile:dev2|double_port:port1|altsyncram:ram_rtl_2|altsyncram_p7j1:auto_generated|ram_block1a0~portb_address_reg2 To : regfile:u1|double_port:port1|altsyncram:ram_rtl_0|altsyncram_p7j1:auto_generated|ram_block1a0~porta_datain_reg11 From Clock : CLOCK_50 To Clock : CLOCK_50 Failed Paths : 0 Type : Clock Setup: 'SW[17]' Slack : N/A Required Time : None Actual Time : 97.50 MHz ( period = 10.256 ns ) From : risc_cpu:cpu0|regfile:dev2|double_port:port1|altsyncram:ram_rtl_2|altsyncram_p7j1:auto_generated|ram_block1a0~portb_address_reg2 To : risc_cpu:cpu0|regfile:dev2|double_port:port2|altsyncram:ram_rtl_1|altsyncram_p7j1:auto_generated|ram_block1a0~porta_datain_reg15 From Clock : SW[17] To Clock : SW[17] Failed Paths : 0 Type : Clock Hold: 'CLOCK_50' Slack : Not operational: Clock Skew > Data Delay Required Time : None Actual Time : N/A From : risc_cpu:cpu0|state.IFE To : risc_cpu:cpu0|state.IFE From Clock : CLOCK_50 To Clock : CLOCK_50 Failed Paths : 4629 Type : Total number of failed paths Slack : Required Time : Actual Time : From : To : From Clock : To Clock : Failed Paths : 4629 --------------------------------------------------------------------------------------
Maintained by John Loomis, last updated Wed Apr 21 12:55:38 2010