Verilog code and testbnench for FIFO to multiplier to RAM
Only the transmission of a single data is completed. Big data needs to be modified tb or basic connections.
FIFO.v
//synchronous fifo module FIFO_syn #( parameter WIDTH = 16, // the fifo wide parameter DEPTH = 1024, // depth parameter ADDR_WIDTH = clogb2(DEPTH) // bit wide // parameter PROG_EMPTY = 100, // this what we set to empty // parameter PROG_FULL = 800 // this what we set to full ) ( input sys_clk, input sys_rst_n , input wr_en, input rd_en, input [WIDTH-1: 0] din , output reg full, output reg empty , /// 1 is real empty 0 is no empty output reg [WIDTH-1:0] dout ); //================================================ ========================================// // define parameter and internal signals // //================================================ ======================================// reg [WIDTH-1 : 0] ram[DEPTH-1 : 0] ; // this we set a 15:0 total 1024 number ram reg [ADDR_WIDTH-1 : 0] wr_addr ; // this is write pointer reg [ADDR_WIDTH-1 : 0] rd_addr ; // this is read pointer reg [ADDR_WIDTH-1 : 0] fifo_cnt; //================================================ =========================================// // next is main code // //================================================ =========================================// // we set a function let me to count the number function integer clogb2; // remember integer has symbol reg has no symbol input[31:0]value; begin value=value-1; for(clogb2=0;value>0;clogb2=clogb2 + 1) value=value>>1; end endfunction // this you can see from the PPT 5-74 //================================================ === next is used to read always@(posedge sys_clk or negedge sys_rst_n) begin if(sys_rst_n == 0) rd_addr <= {<!-- -->ADDR_WIDTH{<!-- -->1'b0}}; else if(rd_en & amp; & amp; !empty) begin rd_addr <= rd_addr + 1'd1; dout <= ram[rd_addr]; end else begin rd_addr <= rd_addr; dout <= dout; end end //================================================ === next is used to write always@(posedge sys_clk or negedge sys_rst_n) begin if(sys_rst_n == 0) begin wr_addr <= {<!-- -->ADDR_WIDTH{<!-- -->1'b0}} ; // this let pointer to zero end else if( wr_en & amp; & amp; !full ) begin // no full and wr_en and whether to write prog_full there wr_addr <= wr_addr + 1'b1; ram[wr_addr] <= din; end else wr_addr <= wr_addr; end //================================================ ============== next is used to set fifo_cnt always@(posedge sys_clk or negedge sys_rst_n ) begin if(sys_rst_n == 0) begin fifo_cnt <= {<!-- -->ADDR_WIDTH{<!-- -->1'b0}}; end else if(wr_en & amp; & amp; !full & amp; & amp; !rd_en) begin fifo_cnt <= fifo_cnt + 1'b1; end else if(rd_en & amp; & amp; !empty & amp; & amp; !wr_en) begin fifo_cnt <= fifo_cnt - 1'b1; end else fifo_cnt <= fifo_cnt; end //================================================ ========== next is empty // we set counter so when the count is zero empty always@(posedge sys_clk or negedge sys_rst_n) begin if(sys_rst_n == 0) begin empty <= 1'b1; // begin we set empty to high end // there is two possibilties first no write fifo_cnt is all zero //second is no write it will be change to zero is just a will empty signal else empty <= (!wr_en & amp; & amp; (fifo_cnt[ADDR_WIDTH-1:1] == 'b0)) & amp; & amp;((fifo_cnt[0] == 1'b0) || rd_en ); end //================================================ ============ next is full always@(posedge sys_clk or negedge sys_rst_n) begin if(sys_rst_n == 0 ) full <= 1'b1;//reset:1 else full <= (!rd_en & amp; & amp; (fifo_cnt[ADDR_WIDTH-1:1]=={<!-- -->(ADDR_WIDTH-1){<!-- -->1'b1}} )) & amp; & amp; ((fifo_cnt[0] == 1'b1) || wr_en); end endmodule
multiplier.v
module uumultiplier #( parameter NUMBER1 = 8 , parameter NUMBER2 = 8 )( input [NUMBER1-1 : 0] input1 , input [NUMBER2-1 : 0] input2 , inputclk, input rst_n , input begin_en, output reg finish_en , output reg [NUMBER1 + NUMBER2 : 0] out ); //================================================ ======================================\ // define parameter and internal signal \ //================================================ ======================================\ reg [1:0] LCD = 2'b10; reg [1:0] LCD1; //================================================ ==========================================\ // next is main code \ //================================================ ===========================================\ always@(posedge clk or negedge rst_n) begin if(rst_n == 0) begin out <= 0 ; end else LCD1 <= LCD ; end always@(posedge clk or negedge rst_n) begin if(rst_n == 0) begin out <= 0 ; end else if(begin_en & amp; & amp; finish_en ) begin out <= input1 * input2 ; LCD <= {<!-- -->LCD[0],LCD[1]}; end else out <= out ; end always@(posedge clk or negedge rst_n) begin if(rst_n == 0) begin finish_en <= 1'b1; end else if(LCD == LCD1) begin finish_en <= 1'b1; end else finish_en <= 1'b0; end endmodule
RAM.v
//DUal ended RAM module RAM #( parameter WIDTH = 8 , parameter DEPTH = 16 , parameter ADD_WIDTH = clogb2(DEPTH) )( input wr_clk, input rd_clk, input wr_en, input rd_en, input [WIDTH-1 : 0 ] din , input [ADD_WIDTH-1 : 0] wr_address , output reg [WIDTH-1 : 0 ] dout , input [ADD_WIDTH-1 : 0] rd_address ); //================================================ ==================================\ // define parameter and internal signal \ //================================================ ==================================\ reg [WIDTH - 1 : 0 ] ram [DEPTH - 1 : 0] ; //================================================ ==================================\ // next is main code \ //================================================ ==================================\ function integer clogb2; input [31:0] value; begin value = value - 1; for(clogb2 = 0; value > 0; clogb2 = clogb2 + 1) value = value >> 1 ; end endfunction // write always@(posedge wr_clk) begin if(wr_en) begin ram[wr_address] <= din; end end //read always@(posedge rd_clk) begin if(rd_en) begin dout <= ram[rd_address]; end end endmodule
top.v
module dig_top #( parameter FIFO_WIDTH = 8 , parameter FIFO_DEPTH = 8 , parameter FIFO_ADDR_WIDTH = clogb2(FIFO_DEPTH) , parameter NUMBER1 = 8 , parameter NUMBER2 = 2, parameter RAM_WIDTH = NUMBER1 + NUMBER2 + 1 , parameter RAM_DEPTH = 8 , parameter RAM_ADDR_WIDTH = clogb2(RAM_DEPTH) )( input sys_clk, input sys_rst_n , input wr_en, input rd_en, input [FIFO_WIDTH-1 : 0] din , input RAM_rd_en , input [RAM_ADDR_WIDTH-1 : 0] wr_address , input [RAM_ADDR_WIDTH-1 : 0] rd_address , output wire [RAM_WIDTH-1 : 0] dout ); //================================================ =============================\ // define parameter and internal signals \ //================================================ =============================\ wire full; wire empty; wire [FIFO_WIDTH-1 : 0] dout1 ; wire finish_en; wire [RAM_WIDTH-1 : 0 ] dout2 ; //================================================ ===============================\ // next is main code \ //================================================ =================================\ function integer clogb2; input [31:0] value; begin value = value - 1; for( clogb2 = 0 ; value > 0 ; clogb2 = clogb2 + 1) value = value >>1; end endfunction FIFO_syn # ( .WIDTH(FIFO_WIDTH), .DEPTH(FIFO_DEPTH), .ADDR_WIDTH(FIFO_ADDR_WIDTH) ) FIFO_syn_inst ( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .wr_en(wr_en), .rd_en(rd_en), .din(din), .full(full), .empty(empty), .dout(dout1) ); uumultiplier # ( .NUMBER1(NUMBER1), .NUMBER2(2'b10) ) uumultiplier_inst ( .input1(dout1), .input2(2'b10), .clk(sys_clk), .rst_n(sys_rst_n), .begin_en(rd_en), .finish_en(finish_en), .out(dout2) ); RAM # ( .WIDTH(RAM_WIDTH), .DEPTH(RAM_DEPTH), .ADD_WIDTH(RAM_ADDR_WIDTH) ) RAM_inst ( .wr_clk(sys_clk), .rd_clk(sys_clk), .wr_en(finish_en), .rd_en(RAM_rd_en), .din(dout2), .wr_address(wr_address), .dout(dout), .rd_address(rd_address) ); endmodule
top_tb.v
`timescale 1ns/1ns module top_tb #( parameter FIFO_WIDTH = 4 , parameter FIFO_DEPTH = 8 , parameter FIFO_ADDR_WIDTH = 3 , parameter NUMBER1 = 4, parameter NUMBER2 = 2, parameter RAM_WIDTH = 7 , parameter RAM_DEPTH = 8 , parameter RAM_ADDR_WIDTH = 3 ); reg sys_clk; reg sys_rst_n; reg wr_en; reg rd_en; reg [FIFO_WIDTH-1 : 0] din ; reg RAM_rd_en; reg [RAM_ADDR_WIDTH-1 : 0] wr_address ; reg [RAM_ADDR_WIDTH-1 : 0] rd_address; wire [RAM_WIDTH-1 : 0] dout ; reg [11:0] cnt; dig_top # ( .FIFO_WIDTH(FIFO_WIDTH), .FIFO_DEPTH(FIFO_DEPTH), .FIFO_ADDR_WIDTH(FIFO_ADDR_WIDTH), .NUMBER1(NUMBER1), .NUMBER2(NUMBER2), .RAM_WIDTH(RAM_WIDTH), .RAM_DEPTH(RAM_DEPTH), .RAM_ADDR_WIDTH(RAM_ADDR_WIDTH) ) dig_top_inst ( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .wr_en(wr_en), .rd_en(rd_en), .din(din), .RAM_rd_en(RAM_rd_en), .wr_address(wr_address), .rd_address(rd_address), .dout(dout) ); always #5 sys_clk = ~sys_clk; initial begin sys_clk = 1; sys_rst_n = 0; #100 sys_rst_n = 1; end always #10 sys_clk = ~sys_clk; initial begin sys_clk = 0; sys_rst_n = 1; wr_en = 0; rd_en = 0; wr_address = 1; rd_address = 1; #10 sys_rst_n = 0; #10 sys_rst_n = 1; #10 // next is write wr_en = 1; rd_en = 1; din = 2; // RAM read RAM_rd_en = 1; end endmodule