【牛客】7 计数器&存储器&综合
VL50 简易秒表
`timescale 1ns/1ns module count_module( input clk, input rst_n, output reg [5:0]second, output reg [5:0]minute ); always@(posedge clk or negedge rst_n) begin if(~rst_n) second <= 'd0; else if(minute == 60) second <= second; else second <= (second<60)?second + 1:1; end always@(posedge clk or negedge rst_n) begin if(~rst_n) minute <= 'd0; else if(second == 60) minute <= minute + 1; end endmodule
VL51 可置位计数器
狗屎一样的题目,不解释。
`timescale 1ns/1ns module count_module( input clk, input rst_n, input set, input [3:0] set_num, output reg [3:0]number, output reg zero ); reg [3:0]num; always@(posedge clk or negedge rst_n) begin if(~rst_n) num <= 'd0; else if(set) num <= set_num; else num <= num + 1; end always@(posedge clk or negedge rst_n) begin if(~rst_n) number <= 'd0; else number <= num; end always@(posedge clk or negedge rst_n) begin if(~rst_n) zero <= 0; else if(num==0) zero <= 1; else zero <= 0; end endmodule
VL52 加减计数器
根据上一道题改一下就好了。
`timescale 1ns/1ns module count_module( input clk, input rst_n, input mode, output reg [3:0]number, output reg zero ); reg [3:0]num; always@(posedge clk or negedge rst_n) begin if(~rst_n) num <= 'd0; else if(mode) num <= (num<9)?num + 1:0; else num <= (num>0)?num - 1:9; end always@(posedge clk or negedge rst_n) begin if(~rst_n) number <= 'd0; else number <= num; end always@(posedge clk or negedge rst_n) begin if(~rst_n) zero <= 0; else if(num==0) zero <= 1; else zero <= 0; end endmodule
VL53 单端口RAM
这个enb交wen比较合适,使能enb应该同时是读和写的使能。
注意地址7位,深度是128。
`timescale 1ns/1ns module RAM_1port( input clk, input rst, input enb, input [6:0]addr, input [3:0]w_data, output wire [3:0]r_data ); //*************code***********// reg [3:0]ram[0:127]; integer i; always@(posedge clk or negedge rst) begin if(~rst)begin for(i=0;i<128;i=i+1) ram[i] <= 'd0; end else begin if(enb)begin ram[addr] <= w_data; end end end assign r_data=enb?'d0:ram[addr]; //*************code***********// endmodule
VL54 RAM的简单实现
读写分别写一个always即可。
`timescale 1ns/1ns module ram_mod( input clk, input rst_n, input write_en, input [7:0]write_addr, input [3:0]write_data, input read_en, input [7:0]read_addr, output reg [3:0]read_data ); reg [3:0]ram[0:7]; integer i; always@(posedge clk or negedge rst_n) begin if(~rst_n)begin for(i=0;i<8;i=i+1) ram[i] <= 'd0; end else begin if(write_en)begin ram[write_addr] <= write_data; end end end always@(posedge clk or negedge rst_n) begin if(~rst_n)begin read_data <= 'd0; end else begin if(read_en)begin read_data <= ram[read_addr]; end end end endmodule
VL55 Johnson Counter
网上搜了一下约翰逊计数器原理就简单了,把最后一位的反,连到移位寄存器最开头就是扭环形计数器。
`timescale 1ns/1ns module JC_counter( input clk , input rst_n, output reg [3:0] Q ); always@(posedge clk or negedge rst_n) begin if(~rst_n) Q <= 'd0; else Q <= {~Q[0],Q[3:1]}; end endmodule
VL56 流水线乘法器
把四个数相加拆分成两个数相加,从而实现简单的流水线。
`timescale 1ns/1ns module multi_pipe#( parameter size = 4 )( input clk , input rst_n , input [size-1:0] mul_a , input [size-1:0] mul_b , output reg [size*2-1:0] mul_out ); wire [size*2-1:0]temp[0:size-1]; reg [size*2-1:0]adder[0:1]; genvar i; generate for(i=0;i<size;i=i+1) assign temp[i] = mul_a[i]?(mul_b<<i):'d0; endgenerate always@(posedge clk or negedge rst_n) begin if(~rst_n)begin adder[0] <= 'd0; adder[1] <= 'd0; mul_out <= 'd0; end else begin adder[0] <= temp[0] + temp[1]; adder[1] <= temp[2] + temp[3]; mul_out <= adder[0] + adder[1]; end end endmodule
VL57 交通灯
又是一道浪费时间的垃圾题目,j简直就是为了满足题目要求硬凑,具体题目细节参考的【收藏】FPGA数字IC基础刷题Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频) (qq.com)
这里为了让信号提前一个周期输出,需要使用next_state进行判断.
`timescale 1ns/1ns module triffic_light ( input rst_n, //异位复位信号,低电平有效 input clk, //时钟信号 input pass_request, output wire[7:0]clock, output reg red, output reg yellow, output reg green ); reg [7:0]cnt; reg [1:0]state,next_state; localparam S0=0,S1=1,S2=2,S3=3; always@(posedge clk or negedge rst_n) begin if(~rst_n) state <= S0; else state <= next_state; end always@(*) begin case(state) S0:next_state = (cnt==8)?S3:S0;//reset delay S1:next_state = (cnt==1)?S3:S1;//green S2:next_state = (cnt==1)?S1:S2;//yellow S3:next_state = (cnt==1)?S2:S3;//red endcase end always@(posedge clk or negedge rst_n) begin if(~rst_n) cnt <= 'd10; else begin case(state) S0:cnt <= (cnt == 8)?10:cnt-1; S1:begin if(pass_request) cnt <= 10; else cnt <= (cnt == 1)?10:cnt-1; end S2:cnt <= (cnt == 1)?60:cnt-1; S3:cnt <= (cnt == 1)?5:cnt-1; endcase end end always @(posedge clk or negedge rst_n) if(~rst_n)begin red <= 1'd0; yellow <= 1'd0; green <= 1'd0; end else begin case(next_state) S0:begin red <= 1'd0; yellow <= 1'd0; green <= 1'd0; end S1:begin red <= 1'd0; yellow <= 1'd0; green <= 1'd1; end S2:begin red <= 1'd0; yellow <= 1'd1; green <= 1'd0; end S3:begin red <= 1'd1; yellow <= 1'd0; green <= 1'd0; end default:begin red <= 1'd0; yellow <= 1'd0; green <= 1'd0; end endcase end assign clock = cnt; endmodule
VL58 游戏机计费程序
一开始以为充值的那一个周期也会扣钱,后来发现想多了。
`timescale 1ns/1ns module game_count ( input rst_n, //异位复位信号,低电平有效 input clk, //时钟信号 input [9:0]money, input set, input boost, output reg[9:0]remain, output reg yellow, output reg red ); always@(posedge clk or negedge rst_n) begin if(~rst_n) remain <= 'd0; else begin if(set) remain <= remain + money; else if(boost) remain <= (remain<2)?remain:remain-2; else remain <= (remain<1)?remain:remain-1; end end always@(posedge clk or negedge rst_n) begin if(~rst_n)begin yellow <= 1'b0; red <= 1'b0; end else begin if(remain < 10&&remain>10) yellow <= 1'b1; else yellow <= 1'b0; if((remain<2&&boost)||(remain<1&&~boost)) red <= 1'b1; else red <= 1'b0; end end endmodule