-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
406 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,305 @@ | ||
module System_toplevel(NCLR, CLK, SERIAL_OUT); | ||
// This is the design for the assembled CPU and memory. | ||
|
||
// System Inputs and outputs: | ||
input wire NCLR, CLK; // Active low reset and clock signals. | ||
output reg SERIAL_OUT; // Serial output port. | ||
|
||
// Internal nets: | ||
wire SYS_CLR; // Internal system reset (active high). | ||
wire EN_IR; // Enable instruction register. | ||
wire EN_PC; // Enable program counter register. | ||
wire EN_DA; // Enable accumulator register. | ||
wire [15:0] IR_OUT; // Instruction register output. | ||
wire [15:0] RAM_OUT; // Data Out port of RAM. | ||
wire [7:0] PCR_OUT; // Program counter register output. | ||
wire MUX_A_SEL; // Mux A input select signal. | ||
wire MUX_B_SEL; // Mux B input select signal. | ||
wire MUX_C_SEL; // Mux C input select signal. | ||
wire [7:0] ACCR_OUT; // Accumulator register output. | ||
wire [7:0] ALU_IN_A; // A port input of ALU. | ||
wire [7:0] ALU_IN_B; // B port input of ALU. | ||
wire [7:0] ALU_OUT; // output port of ALU. | ||
wire [4:0] ALU_SEL; // ALU operation select. | ||
wire CARRY; // Carry out of ALU. | ||
reg ZERO; // Zero is the unary NOR of ALU_OUT. | ||
wire[7:0] ADDRESS; // RAM memory address. | ||
wire RAM_WE; // RAM write enable, 1 for write, 0 for read. | ||
wire FDCE_OUT; // Output of serial output flip flop. | ||
|
||
// Register SYSTEM_RESET_REG toggles the system reset to each block in the CPU: | ||
register #(.WIDTH(1)) SYSTEM_RESET_REG (.CLK(CLK), .CLR(1'b0), | ||
.CE(1'b1), .D(!NCLR), .Q(SYS_CLR)); | ||
|
||
register #(.WIDTH(16)) INSTRUCTION_REG (.CLK(CLK), .CLR(SYS_CLR), .CE(EN_IR), | ||
.D(RAM_OUT), .Q(IR_OUT)); | ||
|
||
register #(.WIDTH(8)) PROGRAM_COUNTER_REG (.CLK(CLK), .CLR(SYS_CLR), .CE(EN_PC), | ||
.D(ALU_OUT), .Q(PCR_OUT)); | ||
|
||
mux_2_1 #(.WIDTH(8)) MUX_A (.SEL(MUX_A_SEL), .A(ACCR_OUT), .B(PCR_OUT), .Y(ALU_IN_A)); | ||
|
||
mux_2_1 #(.WIDTH(8)) MUX_B (.SEL(MUX_B_SEL), .A(RAM_OUT[7:0]), .B(IR_OUT[7:0]), .Y(ALU_IN_B)); | ||
|
||
Arithmetic_Logic_Unit ALU (.A(ALU_IN_A), .B(ALU_IN_B), .SEL(ALU_SEL), .Cout(CARRY), .Y(ALU_OUT)); | ||
|
||
always @ (ALU_OUT) begin | ||
ZERO = !(|ALU_OUT); | ||
end | ||
|
||
register #(.WIDTH(8)) ACCUMULATOR_REG (.CLK(CLK), .CLR(SYS_CLR), .CE(EN_DA), | ||
.D(ALU_OUT), .Q(ACCR_OUT)); | ||
|
||
mux_2_1 #(.WIDTH(8)) MUX_C (.SEL(MUX_C_SEL), .A(PCR_OUT), .B(IR_OUT[7:0]), .Y(ADDRESS)); | ||
|
||
decoder_2 DECODER (.IR(IR_OUT[15:8]), .Carry(CARRY), .Zero(ZERO), .CLK(CLK), .CE(1'b1), | ||
.CLR(SYS_CLR), .MUXA(MUX_A_SEL), .MUXB(MUX_B_SEL), . MUXC(MUX_C_SEL), | ||
.EN_DA(EN_DA), .EN_PC(EN_PC), .EN_IR(EN_IR), .RAM_WE(RAM_WE), | ||
.ALU_SEL(ALU_SEL)); | ||
|
||
RAM #(.DATA_WIDTH(16), .ADDRESS_WIDTH(8)) RAM_1 (.clk(!CLK), .en(1'b1), | ||
.data_in({8'b0,ACCR_OUT}), .address(ADDRESS), .write(RAM_WE), | ||
.data_out(RAM_OUT)); | ||
|
||
register #(.WIDTH(1)) FDCE (.CLK(CLK), .CLR(SYS_CLR), .CE(&ADDRESS), .D(ACCR_OUT[0]), | ||
.Q(FDCE_OUT)); // Register controlling the serial output of the CPU. | ||
always @ (FDCE_OUT) begin | ||
SERIAL_OUT = !FDCE_OUT; | ||
end | ||
|
||
endmodule | ||
|
||
module mux_2_1 #(parameter WIDTH = 8) (SEL, A, B, Y); | ||
// 2x1 Multiplexer | ||
|
||
// Inputs and outputs: | ||
input wire SEL; // 1 bit input select. | ||
input wire [WIDTH-1:0] A, B; // 8 bit input vectors by default. | ||
output reg [WIDTH-1:0] Y; // 8 bit output vector by default. | ||
|
||
always @(SEL or A or B) begin | ||
// Level sensitive - triggers always block whenever A or B or SEL changes. | ||
if (SEL == 1'b0) begin // If select is 0, output is A. | ||
Y = A; | ||
end else if (SEL == 1'b1) begin // If select is 1, output is B. | ||
Y = B; | ||
end else begin | ||
Y = 'bx; | ||
end | ||
end | ||
endmodule | ||
|
||
module Arithmetic_Logic_Unit (A, B, SEL, Y, Cout); | ||
// ALU | ||
|
||
// Inputs and outputs: | ||
input wire [4:0] SEL; // ALU operation select. | ||
input wire [7:0] A,B; // ALU input ports. | ||
output reg [7:0] Y; // ALU output port. | ||
output reg Cout; // ALU carry out. | ||
|
||
// Parameters define ALU operation to carry out: | ||
parameter ADD = 5'b00000; // Add A + B. | ||
parameter AND = 5'b00001; // Bitwise AND of A & B. | ||
parameter IN_A = 5'b00010; // Input A passed to output. | ||
parameter IN_B = 5'b00011; // Input B passed to output. | ||
parameter SUBTRACT = 5'b01100; // Subtract A - B. | ||
parameter INCR_A = 5'b10100; // Increment A (A+1). | ||
parameter IN_A_2 = 5'b10000; // Input A passed to output. | ||
parameter ADD_A_B_1 = 5'b00100; // Add (A+B)+1. | ||
parameter SUB_A_B_1 = 5'b01000; // Subtract (A-B)-1. | ||
|
||
always @ (A or B or SEL) begin | ||
case(SEL) | ||
ADD: {Cout,Y} = A + B; | ||
AND: Y = A & B; | ||
IN_A: Y = A; | ||
IN_B: Y = B; | ||
SUBTRACT: {Cout, Y} = A - B; | ||
INCR_A: {Cout, Y} = A + 1; | ||
IN_A_2: Y = A; | ||
ADD_A_B_1: {Cout, Y} = (A + B) + 1; | ||
SUB_A_B_1: {Cout, Y} = (A - B) - 1; | ||
default: Y = 'bx; | ||
endcase | ||
end | ||
endmodule | ||
|
||
module register #(parameter WIDTH = 8) (D, CLK, CE, CLR, Q); | ||
// Variable data width register | ||
|
||
// Inputs and outputs: | ||
input wire [WIDTH-1:0] D; // Input data. | ||
input wire CLK, CE, CLR; // Clock, enable and reset inputs. | ||
output reg [WIDTH-1:0] Q; // Output data. | ||
|
||
always @ (posedge CLK or CLR) begin | ||
if (CLR == 1'b1) begin // Asynchronous reset. | ||
Q <= 'b0; | ||
end else begin | ||
if (CE == 1'b1) // Data at D passed to output Q. | ||
Q <= D; | ||
else | ||
Q <= Q; // Data on Q doesn't change. | ||
end | ||
end | ||
endmodule | ||
|
||
module sequence_generator #(parameter WIDTH = 4) (CLK, CLR, CE, Q); | ||
// Ring counter to track current state - Fetch, Decode, Execute or Increment. | ||
|
||
// Inputs and outputs: | ||
input wire CLK, CLR, CE; // Clock, reset and enable inputs. | ||
output reg [WIDTH-1:0] Q; // 4 bit (default) output vector - one hot encoded. | ||
|
||
always @ (posedge CLK or CLR) begin | ||
if (CLR == 1'b1) begin // Asynchronous reset. | ||
// Reset sets Q to 1000 - i.e. resets CPU to Fetch phase. | ||
Q[WIDTH-1] <= 1; | ||
Q[WIDTH-2:0] <= 0; | ||
end else begin | ||
if (CE == 1'b1) begin | ||
// Increment counter if enabled, thus entering the next phase of the | ||
// Fetch, Decode, Execute and Increment cycle. | ||
Q[WIDTH-1] <= Q[0]; | ||
Q = Q >> 1; | ||
end else begin | ||
Q <= Q; // Do not increment counter. | ||
end | ||
end | ||
end | ||
endmodule | ||
|
||
module instruction_decoder (A, OUTPUT_BUS); | ||
// Instruction decoder converts the high byte of the 16 bit instruction | ||
// (which was collected and loaded into the instruction register during | ||
// the Fetch phase) into a one-hot encoded value which indicates what action | ||
// needs to be excuted in the Execute phase. | ||
|
||
// Inputs and outputs: | ||
input wire [7:0] A; // 8 bit instruction input. | ||
output reg [10:0] OUTPUT_BUS; // 11 bit one hot encoded output instruction. | ||
|
||
// The 11 one-hot coded options are shown in the case statement. | ||
always @ (A) begin | ||
case (A[7:4]) | ||
'b0000: OUTPUT_BUS = 11'b10000000000; // Load = OUTPUT_BUS[10] | ||
'b0100: OUTPUT_BUS = 11'b01000000000; // Add = OUTPUT_BUS[9] | ||
'b0001: OUTPUT_BUS = 11'b00100000000; // BitAnd = OUTPUT_BUS[8] | ||
'b0110: OUTPUT_BUS = 11'b00010000000; // Sub = OUTPUT_BUS[7] | ||
'b1010: OUTPUT_BUS = 11'b00001000000; // Input = OUTPUT_BUS[6] | ||
'b1110: OUTPUT_BUS = 11'b00000100000; // Output = OUTPUT_BUS[5] | ||
'b1000: OUTPUT_BUS = 11'b00000010000; // Jump U = OUTPUT_BUS[4] | ||
'b1001: begin | ||
case (A[3:2]) | ||
'b00: OUTPUT_BUS = 11'b00000001000; // Jump Z = OUTPUT_BUS[3] | ||
'b10: OUTPUT_BUS = 11'b00000000100; // Jump C = OUTPUT_BUS[2] | ||
'b01: OUTPUT_BUS = 11'b00000000010; // Jump NZ = OUTPUT_BUS[1] | ||
'b11: OUTPUT_BUS = 11'b00000000001; // Jump NC = OUTPUT_BUS[0] | ||
default: OUTPUT_BUS = 'bx; | ||
endcase | ||
end | ||
default: OUTPUT_BUS = 'bx; | ||
endcase | ||
end | ||
endmodule | ||
|
||
module decoder_2 (IR, Carry, Zero, CLK, CE, CLR, MUXA, MUXB, MUXC, EN_DA, EN_PC, EN_IR, RAM_WE, ALU_SEL); | ||
// Decoder - decodes instructions and outputs control signals to execute instructions. | ||
|
||
// Inputs and outputs: | ||
input wire [7:0] IR; // 8 bit instruction input. | ||
input wire Carry, Zero, CLK, CE, CLR; // Carry from ALU, Zero from ALU, clock, enable and reset. | ||
output reg MUXA, MUXB, MUXC, EN_DA, EN_PC, EN_IR, RAM_WE; // As defined in System_toplevel module. | ||
output reg [4:0] ALU_SEL; // ALU operation select. | ||
|
||
// Internal Nets: | ||
wire FETCH, DECODE, EXECUTE, INCREMENT; // Track current state in Fetch, Decode, Execute & Increment. | ||
wire CARRY_REG, ZERO_REG; // Store outputs of 2 bit register. | ||
wire[10:0] INSTRUCTION; // Track current instruction from instruction_decoder. | ||
reg[10:0] INSTRUCTION_VALID; // INSTRUCTION only available in DECODE and EXECUTE states. | ||
reg LOAD, ADD, BITAND, SUB, INPUT, OUTPUT, JUMP, JUMPZ, JUMPC, JUMPNZ, JUMPNC; | ||
reg EN_ST; // If current instruction is ADD, SUB, or BITAND, enable 2 bit register. | ||
reg JUMP_TAKEN; | ||
wire JUMP_NOT_TAKEN; | ||
reg [4:0] JUMP_CONDITIONS; | ||
reg [4:0] JUMP_INSTRUCTIONS; | ||
|
||
sequence_generator #(.WIDTH(4)) SEQ_GEN (.CLK(CLK), .CE(CE), .CLR(CLR), | ||
.Q({FETCH,DECODE,EXECUTE,INCREMENT})); | ||
instruction_decoder INST_DEC (.A(IR), .OUTPUT_BUS(INSTRUCTION)); | ||
register #(.WIDTH(2)) REG_2_BIT (.CLK(CLK), .CLR(CLR), .CE(EN_ST), .D({Zero,Carry}), | ||
.Q({ZERO_REG,CARRY_REG})); | ||
register #(.WIDTH(1)) FDC (.CLK(CLK), .CLR(CLR), .CE(1'b1), .D(!JUMP_TAKEN), .Q(JUMP_NOT_TAKEN)); | ||
|
||
always @ (FETCH or DECODE or EXECUTE or INCREMENT or INSTRUCTION or CARRY_REG or ZERO_REG) begin | ||
// Instruction only valid during DECODE and EXECUTE states: | ||
if (DECODE | EXECUTE) begin | ||
INSTRUCTION_VALID = INSTRUCTION; | ||
end else begin | ||
INSTRUCTION_VALID ='b0; | ||
end | ||
|
||
// Instructions defined by one hot encoding: | ||
LOAD = INSTRUCTION_VALID[10]; | ||
ADD = INSTRUCTION_VALID[9]; | ||
BITAND = INSTRUCTION_VALID[8]; | ||
SUB = INSTRUCTION_VALID[7]; | ||
INPUT = INSTRUCTION_VALID[6]; | ||
OUTPUT = INSTRUCTION_VALID[5]; | ||
JUMP = INSTRUCTION_VALID[4]; | ||
JUMPZ = INSTRUCTION_VALID[3]; | ||
JUMPC = INSTRUCTION_VALID[2]; | ||
JUMPNZ = INSTRUCTION_VALID[1]; | ||
JUMPNC = INSTRUCTION_VALID[0]; | ||
|
||
// 2 bit status register only enabled during an add, subtract or bitwise AND operations: | ||
EN_ST = (ADD || SUB || BITAND); | ||
|
||
// 11 bit vector for Jump conditions: | ||
JUMP_CONDITIONS = {1'b1,ZERO_REG,CARRY_REG,!ZERO_REG,!CARRY_REG}; | ||
// Concatenating all the Jump instructions available | ||
JUMP_INSTRUCTIONS = {JUMP, JUMPZ, JUMPC, JUMPNZ, JUMPNC}; | ||
|
||
// Detects if any Jump was taken for any Jump instruction type: | ||
JUMP_TAKEN = |(JUMP_INSTRUCTIONS & JUMP_CONDITIONS); // Program counter register is not incremented if a Jump was taken. | ||
|
||
// Conditions for outputs of decoder: | ||
RAM_WE = (EXECUTE & OUTPUT); | ||
ALU_SEL[0] = (BITAND | INPUT | LOAD | JUMP | JUMPZ | JUMPNZ | JUMPC | JUMPNC); | ||
ALU_SEL[1] = (LOAD | INPUT | OUTPUT | JUMP | JUMPZ | JUMPNZ | JUMPC | JUMPNC); | ||
ALU_SEL[2] = (INCREMENT | SUB); | ||
ALU_SEL[3] = SUB; | ||
ALU_SEL[4] = INCREMENT; | ||
MUXA = INCREMENT; | ||
MUXB = (LOAD | ADD | BITAND | SUB); | ||
MUXC = (INPUT | OUTPUT); | ||
EN_IR = FETCH; | ||
EN_DA = (EXECUTE & (LOAD | ADD | SUB | BITAND | INPUT)); | ||
EN_PC = ((INCREMENT & JUMP_NOT_TAKEN) | (EXECUTE & JUMP_TAKEN)); | ||
end | ||
endmodule | ||
|
||
module RAM #(parameter DATA_WIDTH = 16, | ||
parameter ADDRESS_WIDTH = 8) (clk, en, data_in, address, write, data_out); | ||
localparam ADDRESS_DEPTH = 2**(ADDRESS_WIDTH); | ||
|
||
// Inputs and outputs: | ||
input wire clk, en; // Clock and enable signal - Enable = 1 by default for this application. | ||
input wire [DATA_WIDTH-1:0] data_in; // Data input for write operation. | ||
input wire [ADDRESS_WIDTH-1:0] address; // Input for memory address to be written to/read from. | ||
input wire write; // Indicates 1 for write operation, 0 for read operation. | ||
output reg [DATA_WIDTH-1:0] data_out; // Data output for read operation. | ||
|
||
reg [DATA_WIDTH-1:0] memory [0:ADDRESS_DEPTH-1]; // 256x16 bit memory array. | ||
|
||
always @ (posedge clk) begin | ||
if (en && write) begin: WRITE_OPERATION | ||
memory[address] <= data_in; // Write data at input to address. | ||
end else if (en && ~write) begin: READ_OPERATION | ||
data_out <= memory[address]; // Pass data at address to data output. | ||
end else begin | ||
data_out <= {DATA_WIDTH{1'bz}}; | ||
end | ||
end | ||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
`timescale 10ns / 1ns | ||
|
||
module CPU_System_TB(); | ||
// This testbench was used to test the overall assembled system. | ||
// There are 2 tests that can be carried out: a simple test using 6 instructions, | ||
// and a comprehensive test of the CPU's entire range of functionality. | ||
// The simple test can be carried out by setting TEST_1 to 1. By default, | ||
// TEST_1 = 0, which enables the full system test. | ||
// The simple test demonstrates the CPU's ability to handle an overflow (adding 250 & 10). | ||
// The extensive test demonstrate's the CPU's entire instruction set - while complicated, | ||
// the CPU's correct operation for this test can be verified by checking it does not | ||
// get caught in any traps, as indicated by the comments below - i.e. the program counter | ||
// never outputs an address of 0x0E, 0x11, 0x15 or 0x18, and will loop back to the beginning | ||
// of the test once complete. | ||
|
||
reg NCLR, CLK; // Active low reset and clock inputs to CPU. | ||
wire SERIAL_OUT; // Serial output of CPU. | ||
reg TEST_1; // Test select. | ||
|
||
System_toplevel DUT (.CLK(CLK), .NCLR(NCLR), .SERIAL_OUT(SERIAL_OUT)); // Assembled CPU + memory module instantiation. | ||
|
||
always #5 CLK = ~CLK; // 100 ns clock period. | ||
|
||
initial begin | ||
$dumpfile("dump.vcd"); // Dump waveform file | ||
$dumpvars(0); | ||
CLK = 0; // Initialise clock. | ||
NCLR = 0; // Initialise reset. | ||
TEST_1 = 0; // Flag to determine which test instructions to load into RAM. | ||
|
||
// Load the following instructions into the RAM: | ||
|
||
if (TEST_1 == 1) begin: SIMPLE_TEST | ||
DUT.RAM_1.memory[0] = 'b1010000000000110; // INPUT ACC, 6 | ||
DUT.RAM_1.memory[1] = 'b0100000000001010; // ADD ACC, 10 | ||
DUT.RAM_1.memory[2] = 'b1001110000000100; // JUMP NC, 4 | ||
DUT.RAM_1.memory[3] = 'b0000000011111111; // LOAD ACC, 255 | ||
DUT.RAM_1.memory[4] = 'b1110000000000111; // OUTPUT ACC, 7 | ||
DUT.RAM_1.memory[5] = 'b1000000000000000; // JUMP, 0 | ||
DUT.RAM_1.memory[6] = 'b0000000011111010; // DATA: 250 | ||
DUT.RAM_1.memory[7] = 'b0000000000000000; // DATA: 0 | ||
|
||
end else begin: FULL_INSTRUCTION_SET_TEST | ||
DUT.RAM_1.memory['h00] = 'b0000000000000001; // LOAD ACC 0x01 - | ||
DUT.RAM_1.memory['h01] = 'b0100000000000000; // ADD ACC, 0x00 - test NZ NC ACC=1 | ||
DUT.RAM_1.memory['h02] = 'b0100000011111111; // ADD ACC, 0xFF - test Z C ACC=0 | ||
DUT.RAM_1.memory['h03] = 'b0000000010101010; // LOAD ACC 0xAA - | ||
DUT.RAM_1.memory['h04] = 'b0001000000001111; // AND ACC, 0x0F - test NZ NC ACC=0x0A | ||
DUT.RAM_1.memory['h05] = 'b0001000000000000; // AND ACC, 0x00 - test Z NC ACC=0x00 | ||
DUT.RAM_1.memory['h06] = 'b0000000000000001; // LOAD ACC 0x01 - | ||
DUT.RAM_1.memory['h07] = 'b0110000000000001; // SUB ACC, 0x01 - test Z NC ACC=0x00 | ||
DUT.RAM_1.memory['h08] = 'b0110000000000001; // SUB ACC, 0x01 - test NZ C ACC=0xFF | ||
DUT.RAM_1.memory['h09] = 'b1110000011110000; // OUTPUT ACC, 0xF0 - test M[0xF0] = 0xFF | ||
DUT.RAM_1.memory['h0A] = 'b0000000000000000; // LOAD ACC 0x00 - | ||
DUT.RAM_1.memory['h0B] = 'b1010000011110000; // INPUT ACC, 0xF0 - test ACC = 0xFF | ||
DUT.RAM_1.memory['h0C] = 'b0100000000000000; // ADD ACC, 0x00 - test NZ NC ACC=0x01 | ||
DUT.RAM_1.memory['h0D] = 'b1001010000001111; // JUMP NZ, 0x0F - skip trap if correct | ||
DUT.RAM_1.memory['h0E] = 'b1000000000001110; // JUMP 0x0E - trap | ||
DUT.RAM_1.memory['h0F] = 'b0100000000000001; // ADD ACC, 0x01 - test Z NC ACC=0x00 | ||
DUT.RAM_1.memory['h10] = 'b1001000000010010; // JUMP Z, 0x12 - skip trap if correct | ||
DUT.RAM_1.memory['h11] = 'b1000000000010001; // JUMP 0x11 - trap | ||
DUT.RAM_1.memory['h12] = 'b0000000000000010; // LOAD ACC 0x02 | ||
DUT.RAM_1.memory['h13] = 'b0100000011111111; // ADD ACC, 0xFF - test NZ C ACC=0x01 | ||
DUT.RAM_1.memory['h14] = 'b1001100000010110; // JUMP C, 0x16 - skip trap if correct | ||
DUT.RAM_1.memory['h15] = 'b1000000000010101; // JUMP 0x15 - trap | ||
DUT.RAM_1.memory['h16] = 'b0110000000000001; // SUB ACC, 0x01 - test Z NC ACC=0x00 | ||
DUT.RAM_1.memory['h17] = 'b1001110000011001; // JUMP NC, 0x19 - skip trap if correct | ||
DUT.RAM_1.memory['h18] = 'b1000000000011000; // JUMP 0x15 - trap | ||
DUT.RAM_1.memory['h19] = 'b1000000000000000; // JUMP 0x00 - loop | ||
end | ||
|
||
// Assert reset for 5 clock periods at the beginning of the simulation: | ||
repeat(5) begin | ||
@ (posedge CLK) begin | ||
NCLR = 0; | ||
end | ||
end | ||
NCLR = 1; // Turn off reset. | ||
|
||
#1000 $finish; | ||
end | ||
endmodule |
Oops, something went wrong.