EDA Playground lets you type in and run HDL code (using a selection of free and commercial simulators and synthesizers).
It's great for learning HDLs, it's great for testing out unfamiliar things and it's great for sharing code.
You can start typing straight away. But to run your code, you'll need to sign or log in. Logging in with a Google account gives you access to all non-commercial simulators and some commercial simulators:
To run commercial simulators, you need to register and log in with a username and password. Registration is free, and only pre-approved email's will have access to the commercial simulators.
208
package cpu_rtl_pkg;
// opcodes
typedef enum logic [2:0] {HLT, SKZ, ADD, AND, XOR, LDA, STO, JMP} opcode_t;
// sequential states of controller state machine
typedef enum {INST_ADDR, INST_FETCH, INST_LOAD, IDLE, OP_ADDR, OP_FETCH, ALU_OP, STORE} state_t;
endpackage : cpu_rtl_pkg
xxxxxxxxxx
//opcode_operand // addr assembly code
//-------------- // ---- -----------------------------------------------
@00 111_11110 // 00 BEGIN: JMP TST_JMP
000_00000 // 01 HLT //JMP did not work at all
000_00000 // 02 HLT //JMP did not load PC, it skipped
101_11010 // 03 JMP_OK: LDA DATA_1
001_00000 // 04 SKZ
000_00000 // 05 HLT //SKZ or LDA did not work
101_11011 // 06 LDA DATA_2
001_00000 // 07 SKZ
111_01010 // 08 JMP SKZ_OK
000_00000 // 09 HLT //SKZ or LDA did not work
110_11100 // 0A SKZ_OK: STO TEMP //store non-zero value in TEMP
101_11010 // 0B LDA DATA_1
110_11100 // 0C STO TEMP //store zero value in TEMP
101_11100 // 0D LDA TEMP
001_00000 // 0E SKZ //check to see if STO worked
000_00000 // 0F HLT //STO did not work
100_11011 // 10 XOR DATA_2
001_00000 // 11 SKZ //check to see if XOR worked
111_10100 // 12 JMP XOR_OK
000_00000 // 13 HLT //XOR did not work at all
100_11011 // 14 XOR_OK: XOR DATA_2
001_00000 // 15 SKZ
000_00000 // 16 HLT //XOR did not switch all bits
000_00000 // 17 END: HLT //CONGRATULATIONS - TEST1 PASSED!
111_00000 // 18 JMP BEGIN //run test again
@1A 00000000 // 1A DATA_1: //constant 00(hex)
11111111 // 1B DATA_2: //constant FF(hex)
10101010 // 1C TEMP: //variable - starts with AA(hex)
@1E 111_00011 // 1E TST_JMP: JMP JMP_OK
000_00000 // 1F HLT //JMP is broken
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_base_test extends uvm_test;
`uvm_component_utils(cpu_base_test)
cpu_base_env environ;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
environ = cpu_base_env::type_id::create("environ",this);
`uvm_info(get_full_name(), "Build state complete.", UVM_HIGH)
endfunction : build_phase
function void end_of_elaboration_phase(uvm_phase phase);
uvm_top.print_topology();
endfunction : end_of_elaboration_phase
task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info(get_type_name(), "Objection raised",UVM_HIGH)
#1000ns;
phase.drop_objection(this);
`uvm_info(get_type_name(), "Objection dropped",UVM_HIGH)
endtask : run_phase
endclass : cpu_base_test
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_base_env extends uvm_env;
`uvm_component_utils(cpu_base_env)
cpu_base_agent agnt;
cpu_scoreboard scb;
cpu_cov_class Coverage; // no coverage during debug
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
agnt = cpu_base_agent::type_id::create("agnt",this);
scb = cpu_scoreboard::type_id::create("scb",this);
Coverage = cpu_cov_class::type_id::create("Coverage",this); // no coverage during debug
`uvm_info(get_full_name(), "Build state complete.", UVM_HIGH)
endfunction : build_phase
function void connect_phase(uvm_phase phase);
agnt.mntr.item_collected_port.connect(scb.item_collected_export);
agnt.mntr.item_collected_port.connect(Coverage.analysis_export); // no coverage during debug
`uvm_info(get_full_name(), "Connect phase complete.", UVM_HIGH)
endfunction : connect_phase
function void start_of_simulation_phase(uvm_phase phase);
`uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH)
endfunction : start_of_simulation_phase
endclass : cpu_base_env
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_base_agent extends uvm_agent;
cpu_monitor mntr;
cpu_sequencer seqr;
cpu_driver drvr;
`uvm_component_utils_begin(cpu_base_agent)
`uvm_field_enum(uvm_active_passive_enum, is_active, UVM_ALL_ON)
`uvm_component_utils_end
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase (uvm_phase phase);
super.build_phase(phase);
mntr = cpu_monitor::type_id::create("mntr",this);
if(is_active == UVM_ACTIVE) begin
seqr = cpu_sequencer::type_id::create("seqr",this);
drvr = cpu_driver::type_id::create("drvr",this);
end
`uvm_info(get_full_name(), "Build state complete.", UVM_HIGH)
endfunction : build_phase
function void connect_phase (uvm_phase phase);
if(is_active == UVM_ACTIVE)
drvr.seq_item_port.connect(seqr.seq_item_export);
`uvm_info(get_full_name(),"Connect state complete.", UVM_HIGH)
endfunction : connect_phase
endclass : cpu_base_agent
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_sequencer extends uvm_sequencer#(cpu_seq_item);
`uvm_component_utils(cpu_sequencer)
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass : cpu_sequencer
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_driver extends uvm_driver #(cpu_seq_item);
`uvm_component_utils(cpu_driver)
virtual interface cpu_if vif;
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual cpu_if)::get(this,"","vif",vif))
`uvm_fatal("No_vif",{"Virtual interface must be set for: ",get_full_name(),".vif"});
`uvm_info(get_full_name(), "Build state complete.", UVM_HIGH)
endfunction : build_phase
// **** For memory-loaded directed test, will not inject stimulus, its already in memory. Simply collecting packets from monitor to monitor current address state
/*
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
`uvm_info(get_type_name(), $sformatf("Sending Packet :\n%s", req.sprint()),UVM_MEDIUM)
drive();
seq_item_port.item_done();
end
endtask : run_phase
virtual task drive();
@(posedge vif.DRIVER.clk);
//------------ Placeholder
@(posedge vif.DRIVER.clk);
//------------ Placeholder
@(posedge vif.DRIVER.clk);
endtask : drive
*/
endclass : cpu_driver
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_seq_item extends uvm_sequence_item;
logic halt;
logic load_ir;
logic [4:0] pc_addr;
`uvm_object_utils_begin(cpu_seq_item)
`uvm_field_int(halt, UVM_ALL_ON)
`uvm_field_int(load_ir, UVM_ALL_ON)
`uvm_field_int(pc_addr, UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "seq item");
super.new(name);
endfunction
endclass : cpu_seq_item
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_monitor extends uvm_monitor;
`uvm_component_utils(cpu_monitor)
virtual interface cpu_if vif;
uvm_analysis_port#(cpu_seq_item)item_collected_port;
cpu_seq_item trans_collected;
cpu_seq_item trans_collected_clone;
int num_pkts;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction : new
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
trans_collected = cpu_seq_item::type_id::create("trans_collected",this);
trans_collected_clone = cpu_seq_item::type_id::create("trans_collected_clone",this);
item_collected_port = new("item_collected_port", this);
if(!uvm_config_db#(virtual cpu_if)::get(this,"","vif",vif))
`uvm_fatal("No vif",{"virtual interace must be set for: ",get_full_name(),"vif"});
`uvm_info(get_full_name(), "Build state complete.", UVM_HIGH)
endfunction : build_phase
virtual task run_phase(uvm_phase phase);
forever begin
get_inputs();
get_outputs();
castwriteprint_item();
end
endtask : run_phase
virtual task get_inputs();
@(posedge vif.MONITOR.clk);
trans_collected.halt = vif.monitor_cb.halt;
trans_collected.load_ir = vif.monitor_cb.load_ir;
trans_collected.pc_addr = vif.monitor_cb.pc_addr;
endtask : get_inputs
virtual task get_outputs();
@(posedge vif.MONITOR.clk);
/*
trans_collected.clk = vif.monitor_cb.clk;
trans_collected.cntrl_clk = vif.monitor_cb.cntrl_clk;
trans_collected.alu_clk = vif.monitor_cb.alu_clk;
trans_collected.fetch = vif.monitor_cb.fetch;
trans_collected.rst_ = vif.monitor_cb.rst_;
*/
endtask : get_outputs
virtual task castwriteprint_item();
@(posedge vif.MONITOR.clk);
$cast(trans_collected_clone,trans_collected.clone());
`uvm_info(get_type_name(), $sformatf("Print values in MONITOR: \n%s", trans_collected_clone.sprint()), UVM_HIGH)
item_collected_port.write(trans_collected_clone);
num_pkts++;
endtask : castwriteprint_item
virtual function void report_phase(uvm_phase phase);
`uvm_info(get_type_name(),$sformatf("Total number of packets collected in Monitor = %0d", num_pkts),UVM_HIGH)
endfunction : report_phase
endclass : cpu_monitor
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
/*
No assertion coverage applied to full CPU.
*/
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_cov_class extends uvm_subscriber#(cpu_seq_item);
`uvm_component_utils(cpu_cov_class)
cpu_seq_item cov_seq_item;
covergroup cg_pc_addr;
option.comment = "Coverage for CPU program counter address";
cp_pc_addr: coverpoint(cov_seq_item.pc_addr)
{
bins pc_addr = {[0:31]};
}
/*
cp_opcode: coverpoint(cov_seq_item.opcode)
{
bins opcode_range[] = {[0:7]};
}
*/
endgroup : cg_pc_addr
function new (string name, uvm_component parent);
super.new(name, parent);
cg_pc_addr=new();
endfunction
virtual function void write(cpu_seq_item t);
cov_seq_item = t;
cg_pc_addr.sample();
endfunction : write
function void report_phase(uvm_phase phase);
`uvm_info(get_name(),"--------------------------------------------------------------------------",UVM_LOW);
`uvm_info(get_name(),$sformatf("Coverage: Overall coverage is %0.2f %%", cg_pc_addr.get_coverage()),UVM_LOW);
`uvm_info(get_name(),$sformatf("Bin cg_pc_addr.cp_pc_addr: (Tested every address?): %0.2f %%", cg_pc_addr.cp_pc_addr.get_coverage()),UVM_LOW);
//`uvm_info(get_name(),$sformatf("Bin cg_pc_addr.cp_opcode: (Tested every opcode?): %0.2f %%", cg_pc_addr.cp_opcode.get_coverage()),UVM_LOW);
`uvm_info(get_name(),"--------------------------------------------------------------------------",UVM_LOW);
endfunction
endclass : cpu_cov_class
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_scoreboard extends uvm_scoreboard;
`uvm_component_utils(cpu_scoreboard)
uvm_analysis_imp#(cpu_seq_item, cpu_scoreboard) item_collected_export;
cpu_seq_item data;
cpu_seq_item pkt_qu[$];
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
item_collected_export = new("item_collected_export",this);
`uvm_info(get_full_name(), "Build state complete.", UVM_HIGH)
endfunction : build_phase
virtual function void write (cpu_seq_item trans_collected);
`uvm_info(get_type_name(), $sformatf("Print values in SCOREBOARD: \n%s", trans_collected.sprint()), UVM_HIGH)
pkt_qu.push_back(trans_collected);
endfunction : write
virtual task run_phase (uvm_phase phase);
cpu_seq_item seq;
phase.raise_objection(this);
forever begin
wait(pkt_qu.size()>0);
seq=pkt_qu.pop_front();
`uvm_info(get_type_name(), $sformatf("Print address in SCOREBOARD: %h",seq.pc_addr), UVM_MEDIUM)
if (seq.pc_addr == 17) begin
`uvm_info(get_type_name(),$sformatf("CPU test 01 passes! CPU Address (hx%h) == Passing Test Address (hx11)",seq.pc_addr),UVM_MEDIUM)
phase.drop_objection(this);
end
end
endtask : run_phase
endclass : cpu_scoreboard
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
interface cpu_if(
input clk,
input cntrl_clk,
input fetch,
input alu_clk,
input rst_
);
logic halt;
logic load_ir;
logic [4:0] pc_addr;
clocking driver_cb @(posedge clk);
default input #1step output #0;
input pc_addr;
input halt;
input load_ir;
output clk;
output alu_clk;
output cntrl_clk;
output fetch;
output rst_;
endclocking
clocking monitor_cb @(posedge clk);
default input #1step output #0;
input pc_addr;
input halt;
input load_ir;
input clk;
input alu_clk;
input cntrl_clk;
input fetch;
input rst_;
endclocking
modport DRIVER(clocking driver_cb, input clk);
modport MONITOR(clocking monitor_cb, input clk);
`include "assertion_coverage.sv"
endinterface
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
class cpu_base_sequence extends uvm_sequence#(cpu_seq_item);
`uvm_object_utils(cpu_base_sequence)
function new(string name = "cpu_base_sequencer");
super.new(name);
endfunction
// **** For memory-loaded directed test, not injecting stimulus
/*
virtual task body();
repeat(0) begin
req=seq_item::type_id::create("req");
start_item(req);
if(!req.randomize()) begin
`uvm_error("Sequence body", "Randomize Failure!")
end
finish_item(req);
end
endtask
*/
endclass : cpu_base_sequence
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
package testbench_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "sequence_items.sv"
`include "sequencer.sv"
`include "sequence.sv"
`include "driver.sv"
`include "monitor.sv"
`include "agent.sv"
`include "scoreboard.sv"
`include "functional_coverage.sv"
`include "environment.sv"
`include "test.sv"
endpackage : testbench_pkg
xxxxxxxxxx
cpu_rtl_pkg.sv
alu.sv
control.sv
counter.sv
mem.sv
register.sv
mux.sv
xxxxxxxxxx
vcs -licqueue '-timescale=1ns/1ns' '+vcs+flush+all' '+warn=all' '-sverilog' '-f' 'compile_file.f' +incdir+$UVM_HOME/src $UVM_HOME/src/uvm.sv $UVM_HOME/src/dpi/uvm_dpi.cc -CFLAGS -DVCS cpu.sv cpu_testbench_top.sv && ./simv +vcs+lic+wait '-access' '+rw' '+UVM_VERBOSITY=UVM_LOW'
xxxxxxxxxx
/*-----------------------------------------------------------------
taylor.templeton@gmail.com
May 2023
Verification Practice Project
Verify each block -> Verify CPU
-----------------------------------------------------------------*/
import uvm_pkg::*;
`include "uvm_macros.svh"
`include "interface.sv"
`include "testbench_pkg.sv"
module cpu_test;
timeunit 1ns;
timeprecision 100ps;
import cpu_rtl_pkg::*;
logic rst_;
logic [12*8:1] testfile; // temporary storage for test vector file
opcode_t topcode;
logic clk, alu_clk, cntrl_clk, fetch;
//--------------- Multi Clock Generator-----START
//*************CLOCK IMPLEMENTATION NEEDS SIMPLIFICATION****************
`define PERIOD 10
logic master_clk = 1'b1;
logic [3:0] count;
always
#(`PERIOD/2) master_clk = ~master_clk;
always @(posedge master_clk or negedge rst_)
if (~rst_)
count <= 3'b0;
else
count <= count + 1;
assign cntrl_clk = ~count[0];
assign clk = count[1];
assign fetch = ~count[3];
assign alu_clk = ~(count == 4'hc);
//--------------- Multi Clock Generator-----END
//--------------- Initial Reset Generator-----START
initial begin
rst_ = 1;
repeat (2) @(negedge master_clk);
rst_ = 0;
repeat (2) @(negedge master_clk);
rst_ = 1;
end
//--------------- Initial Reset Generator-----END
cpu_if intf(
clk,
cntrl_clk,
fetch,
alu_clk,
rst_
);
cpu cpu1 (
.pc_addr_if(intf.pc_addr),
.halt (intf.halt),
.load_ir(intf.load_ir),
.clk (intf.clk),
.alu_clk (intf.alu_clk),
.cntrl_clk (intf.cntrl_clk),
.fetch (intf.fetch),
.rst_ (intf.rst_)
);
// Set interface in configdb
initial begin
uvm_config_db#(virtual interface cpu_if)::set(uvm_root::get(),"*","vif",intf);
end
// Load test vectors into memory prior to test
initial begin
testfile = {"CPUtest1.dat"};
$readmemb ( testfile, cpu1.mem1.memory );
end
initial begin
run_test("cpu_base_test");
end
// Capture waveform in value change dump
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule
xxxxxxxxxx
xxxxxxxxxx
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : alu_test.sv
// Title : ALU Testbench Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the ALU testbench module
// Notes :
//
///////////////////////////////////////////////////////////////////////////
// SystemVerilog: import package with opcode_t enum type declaration
import cpu_rtl_pkg::*;
module alu (
output logic [7:0] out ,
output logic zero ,
input logic clk ,
input logic [7:0] accum ,
input logic [7:0] data ,
input opcode_t opcode
);
// SystemVerilog: time unit and time precision specification
timeunit 1ns;
timeprecision 100ps;
// SystemVerilog: unique case synthesis intent specification
always @(negedge clk)
unique case ( opcode )
ADD : out <= accum + data;
AND : out <= accum & data;
XOR : out <= accum ^ data;
LDA : out <= data;
HLT,
SKZ,
JMP,
STO : out <= accum;
default : out <= 8'bx;
endcase
// SystemVerilog: always_comb synthesis intent specification
always_comb
zero = ~(|accum);
endmodule
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : control.sv
// Title : Control Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the Control module
// Notes :
//
///////////////////////////////////////////////////////////////////////////
// SystemVerilog package for opcode_t and state_t
import cpu_rtl_pkg::*;
module control (
output logic load_ac ,
output logic mem_rd ,
output logic mem_wr ,
output logic inc_pc ,
output logic load_pc ,
output logic load_ir ,
output logic halt ,
input opcode_t opcode ,
input zero ,
input clk ,
input rst_
);
// SystemVerilog: time units and time precision specification
timeunit 1ns;
timeprecision 100ps;
state_t state;
logic aluop;
assign aluop = (opcode inside {ADD, AND, XOR, LDA});
always_ff @(posedge clk or negedge rst_)
if (!rst_)
state <= INST_ADDR;
else
state <= state.next();
always_comb begin
{mem_rd, load_ir, halt, inc_pc, load_ac, load_pc, mem_wr} = 7'b000_0000;
unique case (state)
INST_ADDR : ;
INST_FETCH: mem_rd = 1;
INST_LOAD : begin
mem_rd = 1;
load_ir = 1;
end
IDLE : begin
mem_rd = 1;
load_ir = 1;
end
OP_ADDR : begin
inc_pc = 1;
halt = (opcode == HLT);
end
OP_FETCH : mem_rd = aluop;
ALU_OP : begin
load_ac = aluop;
mem_rd = aluop;
inc_pc = ((opcode == SKZ) && zero);
load_pc = ( opcode == JMP);
end
STORE : begin
load_ac = aluop;
mem_rd = aluop;
inc_pc = (opcode == JMP);
load_pc = ( opcode == JMP);
mem_wr = ( opcode == STO);
end
endcase
end
endmodule
xxxxxxxxxx
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : counter_test.sv
// Title : Counter Testbench Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the Counter testbench module
// Notes :
//
///////////////////////////////////////////////////////////////////////////
// Verilog2001: port and variable declarations in module definition
module counter (
output logic [4:0] count,
input logic [4:0] data ,
input clk ,
input load ,
input rst_,
input enable
);
// SystemVerilog: time unit and time precision declaration
timeunit 1ns;
timeprecision 100ps;
// SystemVerilog: always_ff
always_ff @(posedge clk or negedge rst_)
// SystemVerilog: priority if
priority if (!rst_)
count <= 0;
else if (load)
count <= data;
// SystemVerilog: postincrement or assignment operator
else if (enable)
count <= count +1; //++;
else count = count;
endmodule
xxxxxxxxxx
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : mem.sv
// Title : Memory Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the memory module
// Notes :
// Synchronous 8x32 Memory Design
// Specification:
// Memory is 8-bits wide and address range is 0 to 31.
// Memory access is synchronous.
// Write data into the memory on posedge of clk when write=1
// Place memory[addr] onto data bus on posedge of clk when read=1
// The read and write signals should not be simultaneously high.
//
///////////////////////////////////////////////////////////////////////////
module mem (
input clk,
input read,
input write,
input logic [4:0] addr,
input logic [7:0] data_in,
output logic [7:0] data_out
);
// SYSTEMVERILOG: timeunit and timeprecision specification
timeunit 1ns;
timeprecision 1ns;
// SYSTEMVERILOG: logic data type
logic [7:0] memory [0:31] ;
always @(posedge clk)
if (write && !read)
// SYSTEMVERILOG: time literals
#1 memory[addr] <= data_in;
// SYSTEMVERILOG: always_ff and iff event control
always_ff @(posedge clk iff ((read == '1)&&(write == '0)) )
data_out <= memory[addr];
endmodule
xxxxxxxxxx
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : register.sv
// Title : Register Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the register module
// Notes :
//
///////////////////////////////////////////////////////////////////////////
module register (
// Verilog2001: port and variable declarations in module definition
// SystemVerilog: logic data type
output logic [7:0] out,
input logic [7:0] data,
input clk,
input enable,
input rst_
);
// SystemVerilog: time unit and time precision declaration
timeunit 1ns;
timeprecision 100ps;
// SystemVerilog: always_ff - sequential behavior intent specification
always_ff @(posedge clk, negedge rst_)
if (!rst_)
out <= 0;
else if (enable)
out <= data;
endmodule
xxxxxxxxxx
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : scale_mux_test.sv
// Title : MUX Testbench Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the mux testbench module
// Notes :
//
///////////////////////////////////////////////////////////////////////////
module scale_mux #(WIDTH = 1)
(output logic [WIDTH-1:0] out,
input logic [WIDTH-1:0] in_a,
input logic [WIDTH-1:0] in_b,
input logic sel_a);
timeunit 1ns;
timeprecision 100ps;
always_comb
unique case (sel_a)
1'b1: out = in_a;
1'b0: out = in_b;
default: out = 'x;
endcase
endmodule
xxxxxxxxxx
///////////////////////////////////////////////////////////////////////////
// (c) Copyright 2013 Cadence Design Systems, Inc. All Rights Reserved.
//
// File name : cpu.sv
// Title : CPU Module
// Project : SystemVerilog Training
// Created : 2013-4-8
// Description : Defines the CPU module
// Notes :
//
///////////////////////////////////////////////////////////////////////////
import cpu_rtl_pkg::*;
module cpu (
output logic halt,
output logic load_ir,
output logic [4:0] pc_addr_if,
input logic clk,
input logic cntrl_clk,
input logic alu_clk,
input logic fetch,
input logic rst_
);
//SystemVerilog: timeunit and timeprecision notation
timeunit 1ns;
timeprecision 100ps;
import cpu_rtl_pkg::*;
logic [7:0] data_out, alu_out, accum, ir_out;
logic [4:0] pc_addr, ir_addr, addr;
opcode_t opcode;
logic load_ac, mem_rd, mem_wr, inc_pc, load_pc, zero;
assign pc_addr_if = pc_addr;
//SystemVerilog: .name port connections
register ac ( .out (accum ),
.data (alu_out),
.clk,
.enable (load_ac),
.rst_
);
register ir ( .out (ir_out),
.data(data_out),
.clk,
.enable (load_ir),
.rst_
);
assign opcode = opcode_t'(ir_out[7:5]);
assign ir_addr = ir_out[4:0];
counter pc ( .count (pc_addr),
.data (ir_addr),
.clk (clk),
.load (load_pc),
.enable (inc_pc),
.rst_
);
alu alu1 ( .out (alu_out),
.zero,
.clk (alu_clk),
.accum,
.data(data_out),
.opcode
);
scale_mux #5 smx( .out (addr),
.in_a (pc_addr),
.in_b (ir_addr),
.sel_a (fetch)
);
mem mem1 ( .clk(~cntrl_clk),
.read (mem_rd),
.write (mem_wr),
.addr ,
.data_in(alu_out) ,
.data_out(data_out)
);
control cntl ( .load_ac,
.mem_rd,
.mem_wr,
.inc_pc,
.load_pc,
.load_ir,
.halt,
.opcode,
.zero,
.clk(cntrl_clk),
.rst_
);
endmodule
Your account is not validated. If you wish to use commercial simulators, you need a validated account.
If you have already registered (or have recently changed your email address), but have not clicked on the link in the email we sent you, please do so. If you cannot find the email, please check your spam/junk folder. Or click here to resend the email.
If you have not already registered for a full account, you can do so by clicking below. You will then need to provide us with some identification information. You may wish to save your code first.
Creating, deleting, and renaming files is not supported during Collaboration. To encourage development of these features for Collaboration, tweet to @EDAPlayground
This playground may have been modified. Please save or copy before starting collaboration.
Your exercise has been submitted.