VL33 非整數倍資料位寬轉換8to12
和上一題一樣的,注意valid_out輸出時加一個valid_in(其實32題也要加,不過不加仿真也能過),
`timescale 1ns/1ns module width_8to12( input clk , input rst_n , input valid_in , input [7:0] data_in , output reg valid_out, output reg [11:0] data_out ); reg [2:0]count; always@(posedge clk or negedge rst_n) begin if(~rst_n) count <= 0; else if(valid_in) count <= (count<2)?count + 1:0; end always@(posedge clk or negedge rst_n) begin if(~rst_n) valid_out <= 0; else if(valid_in&&(count==1||count==2)) valid_out <= 1; else valid_out <= 0; end reg [11:0]data_lock; always@(posedge clk or negedge rst_n) begin if(~rst_n)begin data_lock <= 0; data_out <= 0; end else if(valid_in)begin data_lock <= {data_lock[3:0],data_in}; if(count == 1) data_out <= {data_lock[7:0],data_in[7:4]}; else if(count == 2) data_out <= {data_lock[3:0],data_in}; end end endmodule
VL34 整數倍資料位寬轉換8to16
越做越簡單了,整數倍位寬轉換就非常輕松了,
`timescale 1ns/1ns module width_8to16( input clk , input rst_n , input valid_in , input [7:0] data_in , output reg valid_out, output reg [15:0] data_out ); reg count; always@(posedge clk or negedge rst_n) begin if(~rst_n) count <= 0; else if(valid_in) count <= count + 1; end always@(posedge clk or negedge rst_n) begin if(~rst_n) valid_out <= 0; else if(valid_in && count) valid_out <= 1; else valid_out <= 0; end reg [7:0]data_lock; always@(posedge clk or negedge rst_n) begin if(~rst_n)begin data_lock <= 0; data_out <= 0; end else if(valid_in)begin data_lock <= data_in; if(count == 1) data_out <= {data_lock,data_in}; end end endmodule
VL35 狀態機-非重疊的序列檢測
也是一道比較簡單的題,不過要注意是非重疊檢測,用狀態機比用移位暫存器更方便一點,
`timescale 1ns/1ns module sequence_test1( input wire clk , input wire rst , input wire data , output reg flag ); //*************code***********// reg [2:0]state,next_state; localparam S0=0,S1=1,S2=2,S3=3,S4=4; always@(posedge clk or negedge rst) begin if(~rst) state <= S0; else state <= next_state; end always@(*) begin case(state) S0:next_state = data ? S1 :S0; S1:next_state = data ? S1 :S2; S2:next_state = data ? S3 :S0; S3:next_state = data ? S4 :S2; S4:next_state = data ? S0 :S2; default:next_state = S0; endcase end always@(posedge clk or negedge rst) begin if(~rst) flag <= 0; else if(state == S4 && data) flag <= 1; else flag <= 0; end //*************code***********// endmodule
VL36 狀態機-重疊序列檢測
重疊序列用移位暫存器肯定更方便,不過題目要求用狀態機,同樣也是注意狀態跳變就行了,注意輸出延后了一個周期,可以通過加一個狀態來實作,
`timescale 1ns/1ns module sequence_test2( input wire clk , input wire rst , input wire data , output reg flag ); //*************code***********// reg [2:0]state,next_state; localparam S0=0,S1=1,S2=2,S3=3,S4=4; always@(posedge clk or negedge rst) begin if(~rst) state <= S0; else state <= next_state; end always@(*) begin case(state) S0:next_state = data ? S1 :S0; S1:next_state = data ? S1 :S2; S2:next_state = data ? S3 :S0; S3:next_state = data ? S4 :S2; S4:next_state = data ? S1 :S2; default:next_state = S0; endcase end always@(posedge clk or negedge rst) begin if(~rst) flag <= 0; else if(state == S4) flag <= 1; else flag <= 0; end //*************code***********// endmodule
VL37 時鐘分頻(偶數)
一眼行波計數器,不過輸出定義的是wire,懶得再去改了,
我這里是組合邏輯輸出,其實也不大好,
`timescale 1ns/1ns module even_div ( input wire rst , input wire clk_in, output wire clk_out2, output wire clk_out4, output wire clk_out8 ); //*************code***********// reg [2:0]count; always@(posedge clk_in or negedge rst) begin if(~rst) count <= 0; else count <= count + 1; end assign clk_out2 = count[0]; assign clk_out4 = count[1:0]>0&&count[1:0]<3; assign clk_out8 = count>0&&count<5; //*************code***********// endmodule
VL38 自動販售機1
寫完發現題目出的有點垃圾,輸入d直接在上升沿給值,下降沿恢復,只有半個周期,暈,
狀態機折磨了半天,看了看題解,用計數器確實方便多了,一遍過,
`timescale 1ns/1ns module seller1( input wire clk , input wire rst , input wire d1 , input wire d2 , input wire d3 , output reg out1, output reg [1:0]out2 ); //*************code***********// reg[2:0]count; always@(posedge clk or negedge rst) begin if(~rst)begin count <= 0; out1 <= 0; out2 <= 0; end else begin if(d1) count <= count + 1; else if(d2) count <= count + 2; else if(d3) count <= count + 4; if(count>=3)begin count <= 0; out1 <= 1; out2 <= count -3; end else begin out1 <= 0; out2 <= 0; end end end //*************code***********// endmodule
VL39 自動販售機2
和上一題是一樣的,加了一個sel的判斷,
`timescale 1ns/1ns module seller2( input wire clk , input wire rst , input wire d1 , input wire d2 , input wire sel , output reg out1, output reg out2, output reg out3 ); //*************code***********// reg [2:0]count; always@(posedge clk or negedge rst) begin if(~rst)begin count <= 0; out1 <= 0; out2 <= 0; out3 <= 0; end else begin if(d1) count <= count + 1; else if(d2) count <= count + 2; if(sel)begin if(count >= 5)begin out1 <= 0; out2 <= 1; out3 <= count - 5; count <= 0; end else begin out1 <= 0; out2 <= 0; out3 <= 0; end end else begin if(count >= 3)begin out1 <= 1; out2 <= 0; out3 <= count - 3; count <= 0; end else begin out1 <= 0; out2 <= 0; out3 <= 0; end end end end //*************code***********// endmodule
VL40 占空比50%的奇數分頻
用兩個計數器,一個上升沿計數,一個下降沿計數即可,
不過感覺題目還是有點問題,第一個下降沿復位還沒結束,計數器應該不會累加才對,
`timescale 1ns/1ns module odo_div_or ( input wire rst , input wire clk_in, output wire clk_out7 ); //*************code***********// reg clk_out1; reg clk_out2; reg [2:0]count1; reg [2:0]count2; always@(posedge clk_in or negedge rst) begin if(~rst)begin count1 <= 0; clk_out1 <= 0; end else begin count1 <= (count1 < 6)?(count1 + 1):0; if(count1 == 3 || count1 ==6) clk_out1 <= ~clk_out1; end end always@(negedge clk_in or negedge rst) begin if(~rst)begin count2 <= 0; clk_out2 <= 0; end else begin count2 <= (count2 < 6)?(count2 + 1):0; if(count2 == 3 || count2 ==6) clk_out2 <= ~clk_out2; end end assign clk_out7 = clk_out1 | clk_out2; //*************code***********// endmodule
VL41 任意小數分頻
題目給了明示,要先3次8分頻再7次9分頻,連時鐘切換點都給出來了,
`timescale 1ns/1ns module div_M_N( input wire clk_in, input wire rst, output wire clk_out ); parameter M_N = 8'd87; parameter c89 = 8'd24; // 8/9時鐘切換點 parameter div_e = 5'd8; //偶數周期 parameter div_o = 5'd9; //奇數周期 //*************code***********// reg [6:0]count; reg [3:0]count_e; reg [3:0]count_o; reg clk_MN; always@(posedge clk_in or negedge rst) begin if(~rst) count <= 0; else count <= (count < M_N -1)?(count + 1):0; end always@(posedge clk_in or negedge rst) begin if(~rst)begin count_e <= 0; count_o <= 0; clk_MN <= 0; end else begin if(count <= c89 - 1)begin count_e <= (count_e < div_e -1)?(count_e + 1):0; if(count_e == 0||count_e == div_e/2) clk_MN <= ~clk_MN; end else begin count_o <= (count_o < div_o -1)?(count_o + 1):0; if(count_o == 0||count_o == (div_o-1)/2) clk_MN <= ~clk_MN; end end end assign clk_out = clk_MN; //*************code***********// endmodule
VL42 無占空比要求的奇數分頻
說是無占空比要求,其實tb還是要求的50%,無語,參照VL40即可,
寫完發現其實要求占空比40%,烏魚子,
`timescale 1ns/1ns module odd_div ( input wire rst , input wire clk_in, output wire clk_out5 ); //*************code***********// reg [2:0]count; reg clk_div; always@(posedge clk_in or negedge rst) begin if(~rst)begin count <= 0; clk_div <= 0; end else begin count <= (count < 4)?(count + 1):0; if(count == 0 ||count == 2) clk_div <= ~clk_div; end end assign clk_out5 = clk_div; //*************code***********// endmodule
VL43 根據狀態轉移寫狀態機-三段式
`timescale 1ns/1ns module fsm1( input wire clk , input wire rst , input wire data , output reg flag ); //*************code***********// reg[1:0]state,next_state; localparam S0=0,S1=1,S2=2,S3=3; always@(posedge clk or negedge rst) begin if(~rst) state <= S0; else state <= next_state; end always@(*) begin case(state) S0:next_state = data?S1:S0; S1:next_state = data?S2:S1; S2:next_state = data?S3:S2; S3:next_state = data?S0:S3; default:next_state = S0; endcase end always@(posedge clk or negedge rst) begin if(~rst) flag <= 0; else begin if(state == S3 && data) flag <= 1; else flag <= 0; end end //*************code***********// endmodule
VL44 根據狀態轉移寫狀態機-二段式
兩段式把輸出和狀態轉移條件寫一起,直接通過組合邏輯輸出,
`timescale 1ns/1ns module fsm2( input wire clk , input wire rst , input wire data , output reg flag ); //*************code***********// reg[2:0]state,next_state; localparam S0=0,S1=1,S2=2,S3=3,S4=4; always@(posedge clk or negedge rst) begin if(~rst) state <= S0; else state <= next_state; end always@(*) begin case(state) S0:begin next_state = data?S1:S0; flag =0; end S1:begin next_state = data?S2:S1; flag =0; end S2:begin next_state = data?S3:S2; flag =0; end S3:begin next_state = data?S4:S3; flag =0; end S4:begin next_state = data?S1:S0; flag = 1; end default:begin next_state = S0; flag =0; end endcase end //*************code***********// endmodule
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545298.html
標籤:其他
下一篇:陣列名和指標的區別
