Created
October 17, 2021 20:59
-
-
Save ScienceElectronicsFun/166f5b8e7f453a56d6eed3caea413f17 to your computer and use it in GitHub Desktop.
LaMeres CPU verilog code for Spartan 7 FPGA
This file contains hidden or 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
`timescale 1ns / 1ps | |
// Code was provided by Brock J. LaMeres | |
// See his book "Introduction to Logic Curcuits & Logic Design with Verilog" (2nd edition) | |
// for more detailed discussions | |
// | |
// It was modified for Spartan7 and pared down for simplicity | |
// Only 3 instructions LDA, STA, and BRA to demonstrate simple program | |
// Only a single output port to display result | |
module top | |
(input wire klock, | |
input wire reset, | |
output wire [7:0] port_out_00 | |
); | |
//-- Signal Declarations | |
wire [7:0] memory_data_in; | |
wire [7:0] memory_data_out; | |
wire [7:0] memory_address; | |
wire memory_write; | |
//-- Sub-System Instantiations | |
cpu CPU_1 (.klock (klock), | |
.reset (reset), | |
.to_memory (memory_data_in), | |
.from_memory (memory_data_out), | |
.address (memory_address), | |
.write (memory_write) | |
); | |
memory MEMORY_1 | |
(.klock (klock), | |
.reset (reset), | |
.address (memory_address), | |
.write (memory_write), | |
.data_in (memory_data_in), | |
.data_out (memory_data_out), | |
.port_out_00 (port_out_00) | |
); | |
endmodule | |
module cpu | |
(input wire klock, | |
input wire reset, | |
output wire [7:0] to_memory, | |
input wire [7:0] from_memory, | |
output wire [7:0] address, | |
output wire write); | |
//-- Signal Declarations | |
wire IR_Load; | |
wire [7:0] IR; | |
wire MAR_Load; | |
wire PC_Load; | |
wire PC_Inc; | |
wire A_Load; | |
wire B_Load; | |
wire [2:0] ALU_Sel; | |
wire [3:0] CCR_Result; | |
wire CCR_Load; | |
wire [1:0] Bus1_Sel; | |
wire [1:0] Bus2_Sel; | |
//-- Sub-system Instantiation | |
control_unit CU_1 (.klock (klock), | |
.reset (reset), | |
.write (write), | |
.IR_Load (IR_Load), | |
.IR (IR), | |
.MAR_Load (MAR_Load), | |
.PC_Load (PC_Load), | |
.PC_Inc (PC_Inc), | |
.A_Load (A_Load), | |
.B_Load (B_Load), | |
.ALU_Sel (ALU_Sel), | |
.CCR_Result (CCR_Result), | |
.CCR_Load (CCR_Load), | |
.Bus1_Sel (Bus1_Sel), | |
.Bus2_Sel (Bus2_Sel) | |
); | |
data_path DP_1 (.klock (klock), | |
.reset (reset), | |
.from_memory (from_memory), | |
.to_memory (to_memory), | |
.address (address), | |
.IR_Load (IR_Load), | |
.IR (IR), | |
.MAR_Load (MAR_Load), | |
.PC_Load (PC_Load), | |
.PC_Inc (PC_Inc), | |
.A_Load (A_Load), | |
.B_Load (B_Load), | |
.ALU_Sel (ALU_Sel), | |
.CCR_Result (CCR_Result), | |
.CCR_Load (CCR_Load), | |
.Bus1_Sel (Bus1_Sel), | |
.Bus2_Sel (Bus2_Sel) | |
); | |
endmodule | |
module memory | |
(input wire klock, | |
input wire reset, | |
input wire [7:0] address, | |
input wire write, | |
input wire [7:0] data_in, | |
output reg [7:0] data_out, | |
output reg [7:0] port_out_00 | |
); | |
//-- Signal Declarations | |
wire [7:0] rom_data_out; | |
wire [7:0] rw_data_out; | |
//-- Memory Sub-System Instantiations | |
rom_128x8_sync U1 | |
(.klock(klock), | |
.address(address), | |
.data_out(rom_data_out) | |
); | |
rw_96x8_sync U2 | |
(.klock(klock), | |
.data_in(data_in), | |
.write(write), | |
.address(address), | |
.data_out(rw_data_out) | |
); | |
//---------------------------------------------------------------------- | |
//-- OUTPUT Ports | |
//---------------------------------------------------------------------- | |
//-- port_out_00 (address E0) | |
always @ (posedge klock or negedge reset) | |
begin | |
if (!reset) | |
port_out_00 <= 8'h00; | |
else | |
if ((address == 8'hE0) && (write)) | |
port_out_00 <= data_in; | |
end | |
//---------------------------------------------------------------------- | |
//-- MUX for data out | |
//---------------------------------------------------------------------- | |
always @ (address, rom_data_out, rw_data_out) | |
begin: MUX1 | |
if ( (address >= 0) && (address <= 8'h7F) ) | |
data_out = rom_data_out; | |
else if ( (address >= 8'h80) && (address <= 8'hDF) ) | |
data_out = rw_data_out; | |
end | |
endmodule | |
module alu | |
(input wire [7:0] A, | |
input wire [7:0] B, | |
input wire [2:0] ALU_Sel, | |
output reg [7:0] Result, | |
output reg [3:0] NZVC); | |
always @ (A, B, ALU_Sel) | |
begin | |
case (ALU_Sel) | |
3'b000 : begin //-- Addition | |
//-- Sum and Carry Flag | |
{NZVC[0], Result} = A + B; | |
//-- Negative Flag | |
NZVC[3] = Result[7]; | |
//-- Zero Flag | |
if (Result == 0) | |
NZVC[2] = 1; | |
else | |
NZVC[2] = 0; | |
//-- Two's Comp Overflow Flag | |
if ( ((A[7]==0) && (B[7]==0) && (Result[7] == 1)) || ((A[7]==1) && (B[7]==1) && (Result[7] == 0)) ) | |
NZVC[1] = 1; | |
else | |
NZVC[1] = 0; | |
end | |
//-- other ALU operations go here... | |
default : begin | |
Result = 8'hXX; | |
NZVC = 4'hX; | |
end | |
endcase | |
end | |
endmodule | |
module control_unit | |
(input wire klock, | |
input wire reset, | |
output reg write, | |
output reg IR_Load, | |
input wire [7:0] IR, | |
output reg MAR_Load, | |
output reg PC_Load, | |
output reg PC_Inc, | |
output reg A_Load, | |
output reg B_Load, | |
output reg [2:0] ALU_Sel, | |
input wire [3:0] CCR_Result, | |
output reg CCR_Load, | |
output reg [1:0] Bus1_Sel, | |
output reg [1:0] Bus2_Sel); | |
//-- Parameters for Instruction Pmenomics | |
parameter LDA_IMM = 8'h86; //-- Load Register A with Immediate Addressing | |
parameter STA_DIR = 8'h96; //-- Store Register A to memory (RAM or IO) | |
parameter BRA = 8'h20; //-- Branch Always | |
reg [7:0] current_state, next_state; | |
parameter S_FETCH_0 = 0, //-- Opcode fetch states | |
S_FETCH_1 = 1, | |
S_FETCH_2 = 2, | |
S_DECODE_3 = 3, //-- Opcode decode state | |
S_LDA_IMM_4 = 4, //-- Load A (Immediate) states | |
S_LDA_IMM_5 = 5, | |
S_LDA_IMM_6 = 6, | |
S_LDA_DIR_4 = 7, //-- Load A (Direct) states | |
S_LDA_DIR_5 = 8, | |
S_LDA_DIR_6 = 9, | |
S_LDA_DIR_7 = 10, | |
S_LDA_DIR_8 = 11, | |
S_STA_DIR_4 = 12, //-- Store A (Direct) States | |
S_STA_DIR_5 = 13, | |
S_STA_DIR_6 = 14, | |
S_STA_DIR_7 = 15, | |
S_LDB_IMM_4 = 16, //-- Load B (Immediate) states | |
S_LDB_IMM_5 = 17, | |
S_LDB_IMM_6 = 18, | |
S_LDB_DIR_4 = 19, //-- Load B (Direct) states | |
S_LDB_DIR_5 = 20, | |
S_LDB_DIR_6 = 21, | |
S_LDB_DIR_7 = 22, | |
S_LDB_DIR_8 = 23, | |
S_STB_DIR_4 = 24, //-- Store B (Direct) States | |
S_STB_DIR_5 = 25, | |
S_STB_DIR_6 = 26, | |
S_STB_DIR_7 = 27, | |
S_BRA_4 = 28, //-- Branch Always States | |
S_BRA_5 = 29, | |
S_BRA_6 = 30, | |
S_BEQ_4 = 31, //-- Branch if Equal States | |
S_BEQ_5 = 32, | |
S_BEQ_6 = 33, | |
S_BEQ_7 = 34, | |
S_ADD_AB_4 = 35; //-- Addition States | |
//-------------------------------------------------------- | |
//-- STATE MEMORY | |
always @ (posedge klock or negedge reset) | |
begin: STATE_MEMORY | |
if (!reset) | |
current_state <= S_FETCH_0; | |
else | |
current_state <= next_state; | |
end | |
//-------------------------------------------------------- | |
//-- NEXT STATE LOGIC | |
always @ (current_state, IR, CCR_Result) | |
begin: NEXT_STATE_LOGIC | |
case (current_state) | |
S_FETCH_0 : next_state = S_FETCH_1; //-- Path for FETCH instruction | |
S_FETCH_1 : next_state = S_FETCH_2; | |
S_FETCH_2 : next_state = S_DECODE_3; | |
S_DECODE_3 : if (IR == LDA_IMM) next_state = S_LDA_IMM_4; //-- Register A Instructions | |
else if (IR == STA_DIR) next_state = S_STA_DIR_4; | |
else if (IR == BRA) next_state = S_BRA_4; //-- Branch Always | |
else next_state = S_FETCH_0; | |
S_LDA_IMM_4 : next_state = S_LDA_IMM_5; //-- Path for LDA_IMM instruction | |
S_LDA_IMM_5 : next_state = S_LDA_IMM_6; | |
S_LDA_IMM_6 : next_state = S_FETCH_0; | |
S_STA_DIR_4 : next_state = S_STA_DIR_5; //-- Path for STA_DIR instruction | |
S_STA_DIR_5 : next_state = S_STA_DIR_6; | |
S_STA_DIR_6 : next_state = S_STA_DIR_7; | |
S_STA_DIR_7 : next_state = S_FETCH_0; | |
S_BRA_4 : next_state = S_BRA_5; //-- Path for BRA instruction | |
S_BRA_5 : next_state = S_BRA_6; | |
S_BRA_6 : next_state = S_FETCH_0; | |
S_ADD_AB_4 : next_state = S_FETCH_0; //-- Path for BRA instruction | |
default : next_state = S_FETCH_0; | |
endcase | |
end | |
//-------------------------------------------------------- | |
//-- OUTPUT LOGIC | |
always @ (current_state) | |
begin: OUTPUT_LOGIC | |
case (current_state) | |
S_FETCH_0 : begin //-- Put PC onto MAR to provide address of Opcode | |
IR_Load = 0; | |
MAR_Load = 1; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b01; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_FETCH_1 : begin //-- Increment PC, Opcode will be available next state | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 1; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b00; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_FETCH_2 : begin //-- Put Opcode into IR | |
IR_Load = 1; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_DECODE_3 : begin //-- No outputs, machine is decoding IR to decide which state to go to next | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b00; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
//-------------------------------------------------------------------------------------------------- | |
//-- LDA_IMM | |
//-------------------------------------------------------------------------------------------------- | |
S_LDA_IMM_4 : begin //-- Put PC into MAR to provide address of Operand | |
IR_Load = 0; | |
MAR_Load = 1; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b01; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_LDA_IMM_5 : begin //-- Increment PC, Operand will be available next state | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 1; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b00; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_LDA_IMM_6 : begin //-- Operand is available, latch into A | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 1; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
//-------------------------------------------------------------------------------------------------- | |
//-- STA_DIR | |
//-------------------------------------------------------------------------------------------------- | |
S_STA_DIR_4 : begin //-- Put PC onto MAR to provide address of Operand | |
IR_Load = 0; | |
MAR_Load = 1; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b01; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_STA_DIR_5 : begin //-- Prepare to receive Operand from memory, increment PC | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 1; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_STA_DIR_6 : begin //-- Put Operand into MAR (Leave Bus2=from_memory) | |
IR_Load = 0; | |
MAR_Load = 1; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_STA_DIR_7 : begin //-- Put A onto Bus2, which is connected to "to_memory", assert write | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b01; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 1; | |
end | |
//-------------------------------------------------------------------------------------------------- | |
//-- BRA | |
//-------------------------------------------------------------------------------------------------- | |
S_BRA_4 : begin // -- Put PC onto MAR to provide address of Operand | |
IR_Load = 0; | |
MAR_Load = 1; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b01; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_BRA_5 : begin //-- Prepare to receive Operand from memory | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
S_BRA_6 : begin //-- Put Operand into PC (Leave Bus2=from_memory) | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 1; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b10; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
//-------------------------------------------------------------------------------------------------- | |
//-- OTHERS | |
//-------------------------------------------------------------------------------------------------- | |
default : begin | |
IR_Load = 0; | |
MAR_Load = 0; | |
PC_Load = 0; | |
PC_Inc = 0; | |
A_Load = 0; | |
B_Load = 0; | |
ALU_Sel = 3'b000; | |
CCR_Load = 0; | |
Bus1_Sel = 2'b00; //-- "00"=PC, "01"=A, "10"=B | |
Bus2_Sel = 2'b00; //-- "00"=ALU, "01"=Bus1, "10"=from_memory | |
write = 0; | |
end | |
endcase | |
end | |
endmodule | |
module data_path | |
(input wire klock, | |
input wire reset, | |
input wire [7:0] from_memory, | |
output reg [7:0] to_memory, | |
output reg [7:0] address, | |
input wire IR_Load, | |
output reg [7:0] IR, | |
input wire MAR_Load, | |
input wire PC_Load, | |
input wire PC_Inc, | |
input wire A_Load, | |
input wire B_Load, | |
input wire [2:0] ALU_Sel, | |
output reg [3:0] CCR_Result, | |
input wire CCR_Load, | |
input wire [1:0] Bus1_Sel, | |
input wire [1:0] Bus2_Sel); | |
//-- Signal Declarations | |
reg [7:0] Bus1, Bus2; | |
reg [7:0] MAR, PC; | |
reg [7:0] A, B; | |
wire [7:0] ALU_Result; | |
wire [3:0] NZVC; | |
//--------------------------------------------------- | |
//-- Sub-System Instantiation | |
//--------------------------------------------------- | |
alu ALU_1 | |
(.A (A), | |
.B (B), | |
.ALU_Sel (ALU_Sel), | |
.Result (ALU_Result), | |
.NZVC (NZVC) | |
); | |
//--------------------------------------------------- | |
//-- Continuous Signal Assignments, using procedural to keep signals type reg | |
//--------------------------------------------------- | |
always @ (Bus1, MAR) | |
begin | |
to_memory = Bus1; | |
address = MAR; | |
end | |
//--------------------------------------------------- | |
//-- Multiplexers | |
//--------------------------------------------------- | |
always @ (Bus1_Sel, PC, A, B) | |
begin: MUX_BUS1 | |
case (Bus1_Sel) | |
2'b00 : Bus1 = PC; | |
2'b01 : Bus1 = A; | |
2'b10 : Bus1 = B; | |
default : Bus1 = 8'hXX; | |
endcase | |
end | |
always @ (Bus2_Sel, ALU_Result, Bus1, from_memory) | |
begin: MUX_BUS2 | |
case (Bus2_Sel) | |
2'b00 : Bus2 = ALU_Result; | |
2'b01 : Bus2 = Bus1; | |
2'b10 : Bus2 = from_memory; | |
default : Bus2 = 8'hXX; | |
endcase | |
end | |
//-------------------------------------------------- | |
//-- Registers | |
//-------------------------------------------------- | |
always @ (posedge klock or negedge reset) | |
begin: INSTRUCTION_REGISTER | |
if (!reset) | |
IR <= 8'h00; | |
else | |
if (IR_Load) | |
IR <= Bus2; | |
end | |
always @ (posedge klock or negedge reset) | |
begin: MEMORY_ADDRESS_REGISTER | |
if (!reset) | |
MAR <= 8'h00; | |
else | |
if (MAR_Load) | |
MAR <= Bus2; | |
end | |
always @ (posedge klock or negedge reset) | |
begin: PROGRAM_COUNTER | |
if (!reset) | |
PC <= 8'h00; | |
else | |
if (PC_Load) | |
PC <= Bus2; | |
else if (PC_Inc) | |
PC <= MAR + 1; | |
end | |
always @ (posedge klock or negedge reset) | |
begin: A_REGISTER | |
if (!reset) | |
A <= 8'h00; | |
else | |
if (A_Load) | |
A <= Bus2; | |
end | |
always @ (posedge klock or negedge reset) | |
begin: B_REGISTER | |
if (!reset) | |
B <= 8'h00; | |
else | |
if (B_Load) | |
B <= Bus2; | |
end | |
always @ (posedge klock or negedge reset) | |
begin: CONDITION_CODE_REGISTER | |
if (!reset) | |
CCR_Result <= 8'h00; | |
else | |
if (CCR_Load) | |
CCR_Result <= NZVC; | |
end | |
endmodule | |
module rw_96x8_sync | |
(input wire klock, | |
input wire [7:0] data_in, | |
input wire write, | |
input wire [7:0] address, | |
output reg [7:0] data_out); | |
//-- Signal Declarations | |
reg EN; | |
//-- Create the 96x8 R/W Array | |
reg[7:0] RW[8'h80:8'hDF]; | |
//-- We need an enable signal so that data_out is only updated for valid addresses | |
always @ (address) | |
begin | |
if ( (address >= 8'h80) && (address <= 8'hDF) ) | |
EN = 1'b1; | |
else | |
EN = 1'b0; | |
end | |
//-- Model syncronous behavior | |
always @ (posedge klock) | |
begin | |
if (write && EN) | |
RW[address] = data_in; | |
else if (!write && EN) | |
data_out = RW[address]; | |
end | |
endmodule | |
//---------------------------------------------------------------------- | |
//-- Note(s) : This ROM memory contains the program instructions | |
//-- | |
//-- Address Description | |
//-- ---------------------------------- | |
//-- (x00) | |
//-- : Read Only Memory | |
//-- (x7F) (128x8-bit) | |
//-- ---------------------------------- | |
//-- | |
//---------------------------------------------------------------------- | |
module rom_128x8_sync | |
(input wire klock, | |
input wire [7:0] address, | |
output reg [7:0] data_out); | |
//-- Parameters for Instruction Pmenomics | |
parameter LDA_IMM = 8'h86; //-- Load Register A with Immediate Addressing | |
parameter STA_DIR = 8'h96; //-- Store Register A to memory (RAM or IO) | |
parameter BRA = 8'h20; //-- Branch Always | |
//-- Signal Declarations | |
reg EN; | |
//-- Create 128x8 Array | |
reg[7:0] ROM[0:8'h7F]; | |
//----------------------------------------------------------- | |
//-- Fill ROM Array with Instructions | |
initial | |
begin | |
ROM[0] = LDA_IMM; | |
ROM[1] = 8'hAA; | |
ROM[2] = STA_DIR; | |
ROM[3] = 8'hE0; | |
ROM[4] = BRA; | |
ROM[5] = 8'h00; | |
end | |
//------------------------------------------------------------------- | |
// | |
//-- We need an enable signal so that data_out is only updated for valid addresses | |
always @ (address) | |
begin | |
if ( (address >= 0) && (address <= 8'h7F) ) | |
EN = 1'b1; | |
else | |
EN = 1'b0; | |
end | |
//-- Model Syncronous Behavior | |
always @ (posedge klock) | |
begin | |
if (EN) | |
data_out = ROM[address]; | |
end | |
endmodule |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment