Bare Bones in Verilog

From CPUDev Wiki
Jump to: navigation, search

This page or section is a stub. You can help the wiki by accurately contributing to it.

This tutorial aims to provide the reader with instructions of how to write a simple Verilog implementation of the Bare Bones ISA.

Implementation

This example implementation will contain five upper-level modules: the CPU module, the RAM module, the ROM module, the TTY module and the Clock module.

Do note that the Clock module is used just for the simulation. It's not synthesisable, due to the #1 delay.

CPU Module

TODO

RAM Module

The RAM module features two enable/address/data ports: One for reading and one for writing. Additionally, a clk pin drives the clock signal.

Note that the address ports have 7 bits instead of 8, due to capacity being 128 bytes and not 256 bytes.

module ram
(
	input  wire       clk,
	
	input  wire       r_en,
	input  wire [6:0] r_addr,
	output reg  [7:0] r_data,
	
	input  wire       w_en,
	input  wire [6:0] w_addr,
	input  wire [7:0] w_data
);
	reg [7:0] bytes [127:0];
	
	always @(posedge clk)
	begin
		if (r_en == 1)
		begin
			r_data <= bytes[r_addr];
		end
		if (w_en == 1)
		begin
			bytes[w_addr] <= w_data;
		end
	end
endmodule

ROM Module

The ROM module contains read-only memory. For this reason, there is only one enable/address/data port and this one is just for reading. Additionally, a clk pin drives the clock signal.

Note that the address port has 6 bits instead of 8, due to capacity being 64 bytes and not 256 bytes.

module rom
(
	input  wire       clk,
	
	input  wire       r_en,
	input  wire [5:0] r_addr,
	output reg  [7:0] r_data
);
	reg [7:0] bytes [63:0];
	
	always @(posedge clk)
	begin
		if (r_en == 1)
		begin
			r_data <= bytes[r_addr];
		end
	end
endmodule

TTY Module

The TTY module contains one enable/address/data write-only port. Additionally, a clk pin drives the clock signal.

Note that, while the address port has 6 bits, the TTY module outputs the input byte only when the address is 0x00.

module tty
(
	input  wire       clk,
	
	input  wire       w_en,
	input  wire [5:0] w_addr,
	input  wire [7:0] w_data
);
	always @(posedge clk)
	begin
		if (w_en == 1 && w_addr == 0)
		begin
			$monitor("%c", w_data);
		end
	end
endmodule

Clock Module

The Clock module is the simplest of all. It just switches the clock signal on every tick.

Again, this is not synthesisable, due to the #1 delay.

TODO: (Possibly) add parameters to support various clock speeds. Currently, the half-period is fixed at 1ns by default.

module clock
(
	output reg        clk,
);
	initial
	begin
		clk = 0;
	end
	
	always
	begin
		#1 clk = !clk;
	end
endmodule

Testing

TODO

Next Steps

For starters, you might want to extend the ISA and play a bit with the Verilog code. In the future, however, you might want to design a new ISA from the start up. See Category:Design Considerations for some ideas. Who knows, maybe you will even invent something new!