On-chip Dual Address ROM Design
Verilog Code for Dual Address ROM Design
module romc ( clk,addr1,addr2,dout1,dout2);
input clk ;
input [2:0] addr1 ;
input [2:0] addr2 ;
output [63:0] dout1;
output [63:0] dout2;
reg [63:0] dout1_next ;
reg [63:0] dout2_next ;
reg [63:0] dout1_reg1 ; // First pipeline registers.
reg [63:0] dout2_reg1 ;
reg [63:0] dout1; // Second pipeline registers,
reg [63:0] dout2; // i.e., final outputs.
wire [63:0] loc0 ;
wire [63:0] loc1 ;
wire [63:0] loc2 ;
wire [63:0] loc3 ;
wire [63:0] loc4 ;
wire [63:0] loc5 ;
wire [63:0] loc6 ;
wire [63:0] loc7 ;
assign loc0 = 64'h5B5B5B5B5B5B5B5B ; // ROM data -
assign loc1 = 64'h7E6A4719E7B99682 ; // eight numbers
assign loc2 = 64'h7631CF8A8ACF3176 ; // of 8 bits data
assign loc3 = 64'h6AE782B9477E1996 ; // per location.
assign loc4 = 64'h5BA5A55B5BA5A55B ;
assign loc5 = 64'h4782196A96E77EB9 ;
assign loc6 = 64'h318A76CFCF768A31 ;
assign loc7 = 64'h19B96A827E9647E7 ;
always @ (addr1 or addr2)
begin
case (addr1)
3'b000 : dout1_next = loc0 ;
3'b001 : dout1_next = loc1 ;
3'b010 : dout1_next = loc2 ;
3'b011 : dout1_next = loc3 ;
3'b100 : dout1_next = loc4 ;
3'b101 : dout1_next = loc5 ;
3'b110 : dout1_next = loc6 ;
3'b111 : dout1_next = loc7 ;
default : dout1_next = loc0 ;
endcase
case(addr2)
3'b000 : dout2_next = loc0 ;
3'b001 : dout2_next = loc1 ;
3'b010 : dout2_next = loc2 ;
3'b011 : dout2_next = loc3 ;
3'b100 : dout2_next = loc4 ;
3'b101 : dout2_next = loc5 ;
3'b110 : dout2_next = loc6 ;
3'b111 : dout2_next = loc7 ;
default : dout2_next = loc0 ;
endcase
end
always @ (posedge clk) // First pipeline stage
begin
dout1_reg1 <= dout1_next ; // Pipeline registers.
dout2_reg1 <= dout2_next ;
end
always @ (posedge clk) // Second pipeline
begin
dout1 <= dout1_reg1 ; // Data outputs read using addr1
dout2 <= dout2_reg1 ; // and addr2 respectively.
end
endmodule
Test Bench for Dual Address ROM Design
`define clkperiodby2 5 // Required to generate 100 MHz
module romc_test ( dout1,dout2);
output [63:0] dout1;
output [63:0] dout2;
reg clk ;
reg [2:0] addr1 ;
reg [2:0] addr2 ;
romc
romc1(.clk(clk),.addr1(addr1),.addr2(addr2),.dout1(dout1),.dout2(dout
2));
initial
begin
clk = 1'b0 ;
// Read the ROM contents for all combinations of addresses.
#7 addr1 = 3'b000 ;
addr2 = 3'b111 ;
#10 addr1 = 3'b001 ;
addr2 = 3'b110 ;
#10 addr1 = 3'b010 ;
addr2 = 3'b101 ;
#10 addr1 = 3'b011 ;
addr2 = 3'b100 ;
#10 addr1 = 3'b100 ;
addr2 = 3'b011 ;
#10 addr1 = 3'b101 ;
addr2 = 3'b010 ;
#10 addr1 = 3'b110 ;
addr2 = 3'b001 ;
#10 addr1 = 3'b111 ;
addr2 = 3'b000 ;
#40 $stop ;
end
always
#`clkperiodby2 clk <= ~clk ; // Generate 100 MHz clock.
endmodule
Single Address ROM Design
Specification:
The data table is arranged as eight locations of size, 64 bits. While reading the
ROM, only one byte is retrieved at a time. Since it is read as 64 × 8 bits, i.e., 2 × 8
bits, we need 6 bits of address. It is organized as 8 × 64 bits, and can be read
byte-wise.
Input : clk, a(6-bit)
Output: data (8-bit)
Memory : (8X64) width-64 depth-8. Hence, reg [63:0] mem [7:0]
Variables:
1. to read data byte by byte. Hence, reg [7:0] byte_data [7:0]
2. to store 64-bit data in 8 location. Hence
loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8 (Each of 64-bit wide)
3. intermediate output in combnational block d_next(8-bit)
4. 64-bit output data to be retrieved from memory variable mem,
Hence mem_data(64-bit)
Verilog Code for Single Address ROM Design
module romq (clk, a, d);
input clk;
input [5:0] a;
output [7:0] d;
reg [7:0] d;
wire [7:0] d_next ;
reg [63:0] mem [7:0] ;
reg [7:0] byte_data [7:0] ;
wire [63:0] mem_data ;
wire [63:0] loc0 ;
wire [63:0] loc1 ;
wire [63:0] loc2 ;
wire [63:0] loc3 ;
wire [63:0] loc4 ;
wire [63:0] loc5 ;
wire [63:0] loc6 ;
wire [63:0] loc7 ;
assign loc0 = 64'hFF806C5D4F4C473C ;
assign loc1 = 64'h80805D554C473C37 ;
assign loc2 = 64'h6C5D4F4C473C3C36 ;
assign loc3 = 64'h5D5D4F4C473C3733 ;
assign loc4 = 64'h5D4F4C47403B332B ;
assign loc5 = 64'h4F4C47403B332B23 ;
assign loc6 = 64'h4F4C473C362D251E ;
assign loc7 = 64'h4C473B362D251E19 ;
always @ (loc0 or loc1 or loc2 or loc3 or loc4 or loc5 or loc6 or
loc7)
begin
mem [0] = loc0 ;
mem [1] = loc1 ;
mem [2] = loc2 ;
mem [3] = loc3 ;
mem [4] = loc4 ;
mem [5] = loc5 ;
mem [6] = loc6 ;
mem [7] = loc7 ;
end
assign mem_data = mem [a[5:3]] ;.
always @ (mem_data)
begin
byte_data [0] = mem_data [63:56] ;
byte_data [1] = mem_data [55:48] ;
byte_data [2] = mem_data [47:40] ;
byte_data [3] = mem_data [39:32] ;
byte_data [4] = mem_data [31:24] ;
byte_data [5] = mem_data [23:16] ;
byte_data [6] = mem_data [15:8] ;
byte_data [7] = mem_data [7:0] ;
end
assign d_next = byte_data [a[2:0]] ;
always @ (posedge clk)
d <= d_next ; // Register byte data.
endmodule
Test Bench for Single Address ROM Design
`define clkperiodby2 5
module romq_test ();
wire [7:0] d ;
reg clk ;
reg [5:0] a ;.
romq romq1( .clk(clk), .a(a),.d(d)) ;
integer count ;
initial
begin
clk = 1'b0 ;
#7 a = 0 ;
for (count = 0; count < 64; count = count+1)
#10 a = count ; // Apply new address
#200
$stop ;
end
always
#`clkperiodby2 clk <= ~clk ; // Generate 100 MHz clock.
endmodule