verilator/test_regress/t/t_sv_cpu_code/cpu.sv

230 lines
5.6 KiB
Systemverilog
Raw Normal View History

// DESCRIPTION: Verilator: Large test for SystemVerilog
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2012.
// Contributed by M W Lund, Atmel Corporation.
module cpu
#( parameter
// ...
ID = 1 ) // Not used!
(
// ***************************************************************************
// Module Interface (interfaces, outputs, and inputs)
// ***************************************************************************
// **** Interfaces ****
genbus_if.master dbus,
// **** Outputs ****
// N/A
// **** Inputs ****
input logic clk,
input logic rst
);
// ***************************************************************************
// Regs and Wires
// ***************************************************************************
// **** Program Memory ****
logic [15:0] rom_out;
// **** Register File (RF) ****
logic [7:0] rf[0:15];
// **** Fetch Stage ****
logic [7:0] pc; // PC -> Program counter.
logic [15:0] ir; // IR -> Instruction Register.
// **** Decode ****
logic [3:0] idec_rd;
logic idec_rd_we;
logic [7:0] idec_rd_data;
logic [3:0] idec_rs;
logic [7:0] idec_nextpc; // New PC if change of program flow.
logic idec_coff; // Indicates a change of program flow.
logic [7:0] idec_mem_adr;
logic idec_mem_re;
logic idec_mem_we;
// **** Memory ****
logic [7:0] mem_data; // Data from peripheral.
logic mem_ws; // Waitstate.
// ***************************************************************************
// Program Memory (ROM) Interface
// ***************************************************************************
always_comb
begin: ROM
// - Local Variables -
integer i;
reg [15:0] irom [0:255];
// - Set default -
for ( i = 0; i < 256; i++ )
begin
if ( i < $size(rom) )
irom[i] = rom[i];
else
irom[i] = 16'h0000;
end
rom_out = irom[pc[7:0]];
end
// ***************************************************************************
// Register File (RF)
// ***************************************************************************
always_ff @( posedge clk )
begin: RegFile
// - Local Variables -
integer i;
// - Register File -
for ( i = 0; i < 16; i++ )
begin
if ( rst )
rf[i][7:0] <= 8'h00;
else if ( idec_rd_we & (idec_rd == i[3:0]) )
rf[i] <= idec_rd_data;
end
end
// ***************************************************************************
// Fetch Stage
// ***************************************************************************
// **** Program Counter (PC) / Instruction Register (IR) ****
always_ff @( posedge clk )
begin
if ( rst )
begin
pc <= 8'h00;
ir <= 16'h0000;
end
else //if ( ~mem_ws )
begin
if ( ~idec_coff )
begin
pc <= pc + 1;
ir <= rom_out; // Fetch Instruction.
end
else
begin
pc <= idec_nextpc;
ir <= 16'h0000; // Insert no operation (NOP).
end
end
end
// ***************************************************************************
// Decode/Execute Stage
// ***************************************************************************
always_comb
begin
// - Defaults -
idec_rd = 4'h0;
idec_rd_we = 1'b0;
idec_rd_data = 8'h00;
idec_rs = 4'h0;
idec_nextpc = 8'h00;
idec_coff = 1'b0;
idec_mem_adr = 8'h00;
idec_mem_re = 1'b0;
idec_mem_we = 1'b0;
casez ( ir )
16'h0000:; // NOP (<=> Default)
16'h1???: // JMP imm
begin
idec_nextpc = ir[7:0];
idec_coff = 1'b1;
end
16'h4???: // LDI rd, imm
begin
idec_rd = ir[8+:4];
idec_rd_we = 1'b1;
idec_rd_data = ir[0+:8];
end
16'h8???:
begin // STS imm, rs
idec_mem_adr = ir[0+:8];
idec_mem_we = 1'b1;
idec_rs = ir[8+:4];
end
16'h9???:
begin // LDS rd, imm
idec_mem_adr = ir[0+:8];
idec_mem_we = 1'b1;
idec_rd = ir[8+:4];
idec_rd_we = 1'b1;
idec_rd_data = mem_data[0+:8];
end
endcase
end
// ***************************************************************************
// Memory Access ("Stage")
// ***************************************************************************
// **** Connect to "dbus" ****
always_comb
begin: Conntect
reg [15:0] sdata16;
dbus.mConnect
( ID, // ID
sdata16, // sdata
mem_ws, // ws
{2{rf[idec_rs]}}, // mdata
// adr
{8'h00, idec_mem_adr[7:1], 1'b0},
// we
{idec_mem_adr[0],~idec_mem_adr[0]} & {2{idec_mem_we}},
// re
{idec_mem_adr[0],~idec_mem_adr[0]} & {2{idec_mem_re}}
);
// - Connect 16-bit databus to 8-bit CPU -
mem_data = ( idec_mem_adr[0] ) ? sdata16[15:8] : sdata16[7:0];
end
mPreAdrDecode_resp busproperty;
always_comb
begin: PreAdrDecode
busproperty = dbus.mPreAdrDecode( 0, idec_mem_adr );
end
endmodule // cpu